//------------------------------------------------------------------------------ // ps2.0/water.fx // // This shader simulates water // I would like to thank RadonLabs for letting me develop this // (c) 2003 Georges Camy //------------------------------------------------------------------------------ #include "../lib.fx" float4x4 Model; // the model matrix float4x4 ModelViewProjection; // the model*view*projection matrix float4x4 ModelLightProjection; // the model*light*projection matrix float4 ModelEyePos; // the eye position in model space texture BumpMap0; // wave bump texture CubeMap0; // cubic environment map texture LightModMap; // the light modulation map float Time; // the current time // fog float4 FogDistances = float4( 0.0, 750.0, -25.0, 10.0); // x=near, y=far, z=bottom, w=top float4 FogNearBottomColor = float4( 1.0, 1.0, 1.0, 0.01); // rgb=color, a=intensity float4 FogNearTopColor = float4( 1.0, 1.0, 1.0, 0.00); // rgb=color, a=intensity float4 FogFarBottomColor = float4( 0.8 , 0.85 , 0.86 , 1.0);// rgb=color, a=intensity float4 FogFarTopColor = float4( 0.8 , 0.85 , 0.86 , 0.3); // rgb=color, a=intensity // water material data float4 MatDiffuse = float4(0,0,0.2,1); // the water dark color float4 MatSpecular = float4(0,0.5,0.6,1); // the water light color float MatFresnel = 8; // fresnel term reflection/refraction // geometry: wave constants for 5 waves: amplitude, phase, omega, freq float4 WaveParams[] = { { -0.0368069, 0.00253061, 1.52005, 0.241924 }, { 0.00235418, 0.00267063, 2.7365, 0.435527}, { -0.0298042, -0.0892409, 2.52404, 0.401714}, {0.0361108 , 0.0233059, 2.03394,0.323711 }, { -0.0109379, -0.00972796,3.46456 ,0.551403 }, }; float2 WaveDirs[] = { 0.470025 , 0.170519, 0.387961 , -0.315415, 0.499167 , -0.028842, 0.464146 , -0.185926, 0.373996 , 0.331854, }; //------------------------------------------------------------------------------ // shader input/output declarations //------------------------------------------------------------------------------ struct VsInput { float4 position : POSITION; float3 N : NORMAL; float3 T : TANGENT; float3 B : BINORMAL; float2 uv0 : TEXCOORD0; }; struct VsOutput { float4 position : POSITION; float2 uv0 : TEXCOORD0; // bump 0 tex coord float2 uv1 : TEXCOORD1; // bump 1 tex coord float3 normal : TEXCOORD2; // normal to vertex float3 tangentToWorldSpace0 : TEXCOORD3; // first row of 3x3 matrix float3 tangentToWorldSpace1 : TEXCOORD4; // second row of 3x3 matrix float3 tangentToWorldSpace2 : TEXCOORD5; // third row of 3x3 matrix float3 view : TEXCOORD6; // view vector float4 lightPos : TEXCOORD7; // vertex position in light // projection space float4 fog : COLOR0; // fog }; struct PsOutput { float4 color : COLOR; }; //------------------------------------------------------------------------------ // Texture samplers //------------------------------------------------------------------------------ #include "../lightsampler.fx" sampler Bump0Sampler = sampler_state { Texture = ; AddressU = Wrap; AddressV = Wrap; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; MipMapLodBias = -2.75; }; sampler EnvSampler = sampler_state { Texture = ; AddressU = Wrap; AddressV = Wrap; AddressW = Wrap; MinFilter = Linear; MagFilter = Linear; MipFilter = None; }; //------------------------------------------------------------------------------ // The vertex shader //------------------------------------------------------------------------------ VsOutput vsMain(const VsInput vsIn) { VsOutput vsOut; // Make waves int i = 0; float h = 0.0f; for (i = 0; i < 5; i++) { h += WaveParams[i].x * (float) sin(WaveParams[i].y + WaveParams[i].z + WaveParams[i].w * (Time + WaveDirs[i].x*vsIn.position.x + WaveDirs[i].y*vsIn.position.z)); Time = Time + 0.00002f; } if (h>=0) h*=5; float3 pos = vsIn.position + float4(0,h,0,0); // Transform position from object space to clip space vsOut.position = transformStatic(pos, ModelViewProjection); // compute the 3x3 transform matrix from tangent to world (cube) space float3x3 objToTangentSpace; objToTangentSpace[0] = 3.0f * vsIn.T; objToTangentSpace[1] = 3.0f * vsIn.B; objToTangentSpace[2] = vsIn.N; vsOut.tangentToWorldSpace0.xyz = mul(objToTangentSpace, Model[0].xyz); vsOut.tangentToWorldSpace1.xyz = mul(objToTangentSpace, Model[1].xyz); vsOut.tangentToWorldSpace2.xyz = mul(objToTangentSpace, Model[2].xyz); // for drifting clouds... vsOut.lightPos = transformStatic(pos, ModelLightProjection); vsOut.lightPos.x += Time * 0.15; vsOut.lightPos.y += Time * 0.15; vsOut.lightPos.w *= 7.5f; // world space view vector float3 worldEye = transformStatic(ModelEyePos, Model); float3 worldPos = transformStatic(vsIn.position, Model); vsOut.view = normalize(worldEye - worldPos); // fog vsOut.fog = fog(vsIn.position, worldPos, ModelEyePos, FogDistances, FogNearBottomColor, FogNearTopColor, FogFarBottomColor, FogFarTopColor); // generate bump texture coordinates vsOut.uv0 = vsIn.uv0 + 0.001 * (Time + WaveDirs[1]*vsIn.position.xz); vsOut.uv1 = vsIn.uv0 + 0.005 * (Time + WaveDirs[1]*vsIn.position.xz); // pass normal for this vertex vsOut.normal = vsIn.N; return vsOut; } //------------------------------------------------------------------------------ // The pixel shader //------------------------------------------------------------------------------ PsOutput psMain(VsOutput psIn) { PsOutput psOut; // sample light map color float4 lightModulate; if (psIn.lightPos.w >= 0.0f) { lightModulate = tex2Dproj(LightSampler, psIn.lightPos); } else { lightModulate = float4(0.0, 0.0, 0.0, 0.0); } // sample bump map float4 bump0 = 2.0f * (tex2D(Bump0Sampler, psIn.uv0) - 0.5f); float4 bump1 = 2.0f * (tex2D(Bump0Sampler, psIn.uv1) - 0.5f); bump0 = (bump0 + bump1) * 0.5; // get bump vector in world (cube) coordinated float3x3 tangentToWorldSpace; tangentToWorldSpace[0] = psIn.tangentToWorldSpace0; tangentToWorldSpace[1] = psIn.tangentToWorldSpace1; tangentToWorldSpace[2] = psIn.tangentToWorldSpace2; float3 bump = mul(tangentToWorldSpace, bump0.xyz); // Calculate a fresnel term for the refraction float fres = 1+dot(psIn.view, psIn.normal); fres = 1/pow(fres, 3); // get refracted color float3 refractedColor = lerp(float3(0,0,0.2), float3(0,0.6,0.5), fres); // Calculate a fresnel term for the reflection fres = 1+dot(psIn.view.xyz, bump); fres = 1/pow(fres, 8); // get reflected color float3 reflectedView = reflect(-psIn.view.xyz, bump); float3 reflectedColor = texCUBE(EnvSampler, reflectedView); // final color float3 color = lerp(refractedColor, reflectedColor, fres) * lightModulate; psOut.color.rgb = lerp(color.rgb, psIn.fog.rgb, psIn.fog.a); psOut.color.a = 1.0f; return psOut; } //------------------------------------------------------------------------------ // The technique. //------------------------------------------------------------------------------ technique t0 { pass p0 { ZWriteEnable = true; ColorWriteEnable = RED|GREEN|BLUE|ALPHA; ZEnable = True; ZFunc = LessEqual; AlphaBlendEnable = False; CullMode = Cw; AlphaTestEnable = True; AlphaFunc = GreaterEqual; AlphaRef = 10; VertexShader = compile vs_2_0 vsMain(); PixelShader = compile ps_2_0 psMain(); } }