Crystal shader

From GameStudio Wiki

Jump to: navigation, search

Contents

Crystal shader

based on the crystal shader used in the "Life on the Bleeding Edge" demo from nvidia, more infos: http://developer.nvidia.com/object/nvision08-DemoTeam.html

The crystal.fx file:

/******************************************
**	crystal shader                       **
**  based on the crystal shader used in  **
**  the "Life on the Bleeding Edge" demo **
**  from nvidia							 **
*******************************************
** credits:                              **
** ChrisB                                **
** http://www.swollen-eyeballs.org       **
** http://developer.nvidia.com/object/nvision08-DemoTeam.html **
******************************************/


// transformations
float4x4 matWorld;
float4x3 matView;
float4x4 matViewProj;
float4x3 matWorldView;
float4x4 matWorldViewProj;
float4x3 matWorldInv;
float4x3 matViewInv;
float3 vecViewPos;
float4 vecSunDir;
float4 vecSkill1;
float4 vecAmbient;


texture entSkin1;
texture mtlSkin1;

samplerCUBE EnvironmentSampler = sampler_state
{ 
    Texture = <mtlSkin1>;
    MipFilter = LINEAR;
    MinFilter = LINEAR;
    MagFilter = LINEAR;
};

// vertex shader output structure
struct VS_OUTPUT
{
    float4 Pos  : POSITION;
    float3 view : TEXCOORD0;
    float3 normal : TEXCOORD3;
    float3 vPos : TEXCOORD2;
    float3 eye : TEXCOORD1;
};


VS_OUTPUT VS(
    float4 InPos  : POSITION,
    float3 InNormal : NORMAL )
{
    VS_OUTPUT Out = (VS_OUTPUT)0;

    // transform the position and normal
    Out.vPos = mul(InPos, matWorld).xyz;         // position (view space)
  

    Out.normal = mul(InNormal, matWorld);   // normal (view space)
    Out.view = vecViewPos.xyz;

    Out.Pos  = mul(InPos, matWorldViewProj);              // position (projected)    
    Out.eye = Out.vPos-vecViewPos;
    return Out;
}

float fresnelRefl(float3 n, float3 v, float f)
{
	float base = 1.0 - dot(n,v);
	float expo = pow(base, 2.0);
	return expo + f*(1.0 - expo);
}

float intersectRaySphere(float3 dst, float3 dir) {
	float B = dot(dst, dir);
	float C = dot(dst, dst) - 1;
	float D = B*B - C;
	return D > 0 ? -B - sqrt(D) : 0;
}

float3 facetNormal(float3 n, float facetSize)
{
	float3 scaledNormal = n*facetSize;
	float3 scaleandround = float3( round(scaledNormal.x), round(scaledNormal.y), round(scaledNormal.z));
	return normalize(scaleandround);
}

float4 PS ( VS_OUTPUT In) : COLOR
{
    float4 OutColor=0;
    float3 color = vecAmbient.rgb;
    float3 normal = normalize(In.normal);//
    normal = lerp(normal, facetNormal(normal, vecSkill1.y), vecSkill1.z);
    float3 viewDir = normalize(In.eye);//In.vPos - In.view);
    float3 reflectVec = reflect(viewDir, normal);    
    float4 reflectColor = texCUBE(EnvironmentSampler, reflectVec);
    
    float diff = saturate(dot(normal, -vecSunDir.xyz));
    float3 vReflectionTS = normalize( 2 * dot( viewDir, normal ) * normal - viewDir );
           
    float fRdotL = saturate( dot( vReflectionTS, vecSunDir.xyz ));
    float spec = pow(fRdotL, 10)*1;
    float index=vecSkill1.x;
    float f0=pow((1.0-index)/(1.0+index), 2.0);
    float f0_out=pow((index-1.0)/(1.0+index), 2.0);
    float fresnel = fresnelRefl(normal, -viewDir, f0);
    
    float3 T0 = refract(viewDir, normal, 1.0/index);
    float t=intersectRaySphere(normal, -T0);
    float3 normal2 = facetNormal(normalize(normal-t*T0), vecSkill1.y);
    float3 T1 = refract(T0, -normal2, 1.0/index);
    float fresnel1 = (fresnelRefl(normal2, T0, f0_out));
    float4 refractColor = texCUBE(EnvironmentSampler, T1);
    
    
    float diff2 = saturate(dot(normal2, -vecSunDir.xyz));
    float3 vReflectionTS2 = normalize( 2 * dot( T0, normal2 ) * normal2 - T0 );
           
    float fRdotL2 = saturate( dot( vReflectionTS2, vecSunDir.xyz ));
    float spec2 = pow(fRdotL2, 10)*1*exp(t*0.5);
    
    
    float3 T2 = reflect(T0, normal2);
    float t2=intersectRaySphere(normal2, -T2);
    float3 normal3 = facetNormal(normalize(normal-t2*T2), vecSkill1.y);
    float3 T3 = refract(T2, -normal3, 1.0/index);
    float fresnel2 =(fresnelRefl(normal3, T2, f0_out));
    float4 refractColor2 = texCUBE(EnvironmentSampler, T3);
    
    OutColor.rgb += reflectColor*color*fresnel;
    OutColor.rgb+=spec*color*2;
    OutColor.rgb+=(1-fresnel)*exp(t*0.5)*((1-fresnel1)*refractColor*color+spec2*color*2+exp(t2*0.75)*(1-fresnel2)*refractColor2*color);
    return OutColor;
}


float4 PS2 ( VS_OUTPUT In) : COLOR
{
    float4 OutColor=0;
    float3 color = vecAmbient.rgb;
    float3 normal = normalize(In.normal);
    normal = lerp(normal, facetNormal(normal, vecSkill1.y), vecSkill1.z);
    float3 viewDir = normalize(In.eye);//In.vPos - In.view);
    float3 reflectVec = reflect(viewDir, normal);    
    float4 reflectColor = texCUBE(EnvironmentSampler, reflectVec);    
    float diff = saturate(dot(normal, -vecSunDir.xyz));
    float3 vReflectionTS = normalize( 2 * dot( viewDir, normal ) * normal - viewDir );           
    float fRdotL = saturate( dot( vReflectionTS, vecSunDir.xyz ));
    float spec = pow(fRdotL, 10)*1;
    float index=vecSkill1.x;
    float f0=pow((1.0-index)/(1.0+index), 2.0);
    float f0_out=pow((index-1.0)/(1.0+index), 2.0);
    float fresnel = fresnelRefl(normal, -viewDir, f0)*1;    
    float3 T0 = refract(viewDir, normal, 1.0/index);
    float4 refractColor = texCUBE(EnvironmentSampler, T0);    
    float spec2 =0;// pow(fRdotL2, 10)*1*exp(t*0.5);    
    OutColor.rgb += reflectColor*color*fresnel;
    OutColor.rgb+=spec*color*2;
    OutColor.rgb+=(1-fresnel)*0.5*refractColor*color+spec2*color*2;
    return OutColor;
}



technique crystal
{
    pass P0
    {
        VertexShader = compile vs_3_0 VS();
        PixelShader  = compile ps_3_0 PS();
    }
}

technique crystal20
{
    pass P0
    {
        VertexShader = compile vs_2_0 VS();
        PixelShader  = compile ps_2_0 PS2();
    }
}


C-Script example:


bmap bmp_cubemap=<mysky+6.tga>;
material mat_crystal
{
	effect="crystal.fx";
	skin1=bmp_cubemap;
	ambient_red=200;
	ambient_green=180;
	ambient_blue=150;	
}

action earth
{
	my.material=mat_crystal;	
	bmap_to_cubemap(bmp_cubemap);
	mat_crystal.skill1=float(1.25);			//vecSkill1
	mat_crystal.skill2=float(5);
	mat_crystal.skill3=float(0);
}


Adjustable through:


material parameter meaning
mtl.ambient_xxx color
mtl.skill1 refractive index
mtl.skill2 facet size
mtl.skill3 facet models normals (0 or 1)


Remarks

First material skin is used for reflections and refraction.

Uses ShaderModel: 3
Has fallback techniques: yes (but not good ones)
Uses fog: no

--ChrisB 19:26, 4 April 2009 (CEST)

Personal tools