//------- Constants -------- float4x4 xCameraViewProjection; float4x4 xLightViewProjection; float4x4 xWorld; float4x4 xView; float4x4 xProjection; float3 xLightDirection; float4 xLightPos; float xLightPower; //For the ambient light realization float4 xCameraPos; float4 xLampPostPos[2]; float xAmbient; //bool xShowNormals; bool xEnableLighting; bool xEnableTexture; float4x4 xLightWorldViewProjection; float xMaxDepth; bool xUseBrownInsteadOfTextures; Texture xUserTexture; sampler textureSampler = sampler_state { Texture = ; mipfilter = LINEAR; }; /* VS_OUTPUT Transform( float4 Position : POSITION, float4 Color : COLOR0, float4 TextureCoordinate : TEXCOORD0 ) { VS_OUTPUT Out = (VS_OUTPUT)0; Out.position = mul(Position, xWorldViewProj); Out.color = Color; Out.textureCoordinate = TextureCoordinate; return Out; } float4 ApplyTexture(VS_OUTPUT vsout) : COLOR { return tex2D(textureSampler, vsout.textureCoordinate).rgba; } float4 PixelShader( VS_OUTPUT vsout ) : COLOR { return vsout.color; } technique TransformAndTexture { pass P0 { vertexShader = compile vs_2_0 Transform(); pixelShader = compile ps_2_0 ApplyTexture(); } } */ float DotProduct(float4 LightPos, float3 Pos3D, float3 Normal) { float3 LightDirection = normalize(LightPos - Pos3D); return dot(LightDirection, Normal); } //------- Technique: Water -------- float4x4 xReflectionView; float xWaveLength; float xWaveHeight; //For the Fresnel term float3 xCamPos; //To realize moving water float xTime; float xWindForce; float4x4 xWindDirection; Texture xReflectionMap; sampler ReflectionSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; Texture xRefractionMap; sampler RefractionSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; Texture xWaterBumpMap; sampler WaterBumpMapSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; struct WaterVertexToPixel { float4 Position : POSITION; float4 ReflectionMapSamplingPos : TEXCOORD1; float2 BumpMapSamplingPos : TEXCOORD2; float4 RefractionMapSamplingPos : TEXCOORD3; float4 Position3D : TEXCOORD4; float3 Normal : TEXCOORD5; }; struct WaterPixelToFrame { float4 Color : COLOR0; }; WaterVertexToPixel WaterVS(float4 inPos : POSITION, float2 inTex: TEXCOORD, float3 inNormal: NORMAL0) { WaterVertexToPixel Output = (WaterVertexToPixel)0; float4x4 preViewProjection = mul (xView, xProjection); float4x4 preWorldViewProjection = mul (xWorld, preViewProjection); float4x4 preReflectionViewProjection = mul (xReflectionView, xProjection); float4x4 preWorldReflectionViewProjection = mul (xWorld, preReflectionViewProjection); Output.Position = mul(inPos, preWorldViewProjection); Output.ReflectionMapSamplingPos = mul(inPos, preWorldReflectionViewProjection); Output.BumpMapSamplingPos = inTex / xWaveLength; Output.RefractionMapSamplingPos = mul(inPos, preWorldViewProjection); Output.Position3D = inPos; //The vector that indicates the movement range of the water float2 moveVector = float2(0, 1); float4 absoluteTexCoords = float4(inTex, 0, 1); float4 rotatedTexCoords = mul(absoluteTexCoords, xWindDirection); Output.BumpMapSamplingPos = inTex/xWaveLength + xTime*xWindForce*moveVector; Output.Normal = normalize(mul(inNormal, (float3x3)xWorld)); return Output; } WaterPixelToFrame WaterPS(WaterVertexToPixel PSIn) { WaterPixelToFrame Output = (WaterPixelToFrame)0; float2 ProjectedTexCoords; ProjectedTexCoords.x = PSIn.ReflectionMapSamplingPos.x/PSIn.ReflectionMapSamplingPos.w/2.0f + 0.5f; ProjectedTexCoords.y = -PSIn.ReflectionMapSamplingPos.y/PSIn.ReflectionMapSamplingPos.w/2.0f + 0.5f; //Bump mapping part float4 bumpColor = tex2D(WaterBumpMapSampler, PSIn.BumpMapSamplingPos); float2 perturbation = xWaveHeight * (bumpColor.rb - 0.5f); float2 perturbatedTexCoords = ProjectedTexCoords + perturbation; //Calculate the refractive color to later combine it with the reflection color float4 reflectiveColor = tex2D(ReflectionSampler, perturbatedTexCoords); float2 ProjectedRefrTexCoords; ProjectedRefrTexCoords.x = PSIn.RefractionMapSamplingPos.x/PSIn.RefractionMapSamplingPos.w/2.0f + 0.5f; ProjectedRefrTexCoords.y = -PSIn.RefractionMapSamplingPos.y/PSIn.RefractionMapSamplingPos.w/2.0f + 0.5f; float2 perturbatedRefrTexCoords = ProjectedRefrTexCoords + perturbation; float4 refractiveColor = tex2D(RefractionSampler, perturbatedRefrTexCoords); //Fresnel part float3 eyeVector = normalize(xCamPos - PSIn.Position3D); //float3 normalVector = float3(0,0,1); float fresnelTerm = dot(eyeVector, PSIn.Normal); float4 combinedColor = refractiveColor*fresnelTerm + reflectiveColor*(1-fresnelTerm); float4 dullColor = float4(0.3f, 0.3f, 0.5f, 1.0f); float dullBlendFactor = 0.2f; Output.Color = dullBlendFactor*dullColor + (1-dullBlendFactor)*combinedColor; return Output; } technique Water { pass Pass0 { VertexShader = compile vs_1_1 WaterVS(); PixelShader = compile ps_2_0 WaterPS(); } } //------- Technique: Colored -------- struct VertexToPixel { float4 Position : POSITION; float4 Color : COLOR0; float LightingFactor: TEXCOORD0; }; struct PixelToFrame { float4 Color : COLOR0; }; VertexToPixel ColoredVS( float4 inPos : POSITION0, float3 inNormal: NORMAL0, float4 inColor: COLOR) { VertexToPixel Output = (VertexToPixel)0; float4x4 preViewProjection = mul (xView, xProjection); float4x4 preWorldViewProjection = mul (xWorld, xCameraViewProjection); Output.Position = mul(inPos, preWorldViewProjection); if(!xEnableTexture) { Output.Color = inColor; //Output.Position3D = inPos; }else { //Output.TextureCoords = inTextureCoords; } //To rotate the model normals according to the model's rotation float3 Normal = normalize(mul(normalize(inNormal), xWorld)); //Output.Normal = normalize(mul(inNormal, (float3x3)xWorld)); //Output.Position3D = mul(inPos, xWorld); Output.LightingFactor = 1; //Output.xLightPower = 1; if (xEnableLighting) { //Output.LightingFactor = dot(Output.Normal, -xLightDirection); Output.LightingFactor = saturate(dot(inNormal, -xLightDirection)+xAmbient); } return Output; } PixelToFrame ColoredPS(VertexToPixel PSIn) { PixelToFrame Output = (PixelToFrame)0; Output.Color = PSIn.Color*PSIn.LightingFactor; /* float DiffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal); if(!xEnableTexture) { //Output.Color = clamp(DiffuseLightingFactor, 0, 1); //Output.Color = clamp(xLightPower + xAmbient,0,1); Output.Color.rgb = PSIn.Position3D * clamp(xLightPower + xAmbient, 0, 1); }else { //Output.Color = tex2D(textureSampler, PSIn.TextureCoords)*DiffuseLightingFactor*xLightPower; } */ return Output; } technique Colored { pass Pass0 { VertexShader = compile vs_1_1 ColoredVS(); PixelShader = compile ps_1_1 ColoredPS(); } } //------- Technique: Textured -------- sampler TextureSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; struct TexVertexToPixel { float4 Position : POSITION; float4 Color : COLOR0; float3 Normal : TEXCOORD0; float2 TextureCoords : TEXCOORD1; float4 LightDirection : TEXCOORD2; }; struct TexPixelToFrame { float4 Color : COLOR0; }; TexVertexToPixel TexturedVS( float4 inPos : POSITION, float3 inNormal: NORMAL, float2 inTexCoords: TEXCOORD0) { TexVertexToPixel Output = (TexVertexToPixel)0; float4x4 preViewProjection = mul (xView, xProjection); float4x4 preWorldViewProjection = mul (xWorld, preViewProjection); Output.Position = mul(inPos, preWorldViewProjection); Output.Normal = mul(normalize(inNormal), xWorld); Output.TextureCoords = inTexCoords; Output.LightDirection.xyz = -xLightDirection; Output.LightDirection.w = 1; return Output; } TexPixelToFrame TexturedPS(TexVertexToPixel PSIn) { TexPixelToFrame Output = (TexPixelToFrame)0; float lightingFactor = 1; if (xEnableLighting) lightingFactor = saturate(saturate(dot(PSIn.Normal, PSIn.LightDirection)) + xAmbient); Output.Color = tex2D(TextureSampler, PSIn.TextureCoords)*lightingFactor; return Output; } technique Textured { pass Pass0 { VertexShader = compile vs_1_1 TexturedVS(); PixelShader = compile ps_1_1 TexturedPS(); } } //------- Technique: MultiTextured -------- Texture xGrassTexture; sampler GrassTextureSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; Texture xSandTexture; sampler SandTextureSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; Texture xRockTexture; sampler RockTextureSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; Texture xSnowTexture; sampler SnowTextureSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; struct MultiTexVertexToPixel { float4 Position : POSITION; float4 Color : COLOR0; float3 Normal : TEXCOORD0; float4 TextureCoords : TEXCOORD1; float4 LightDirection : TEXCOORD2; float4 TextureWeights : TEXCOORD3; float Depth : TEXCOORD4; }; MultiTexVertexToPixel MultiTexturedVS( float4 inPos : POSITION, float3 inNormal: NORMAL, float4 inTexCoords: TEXCOORD0, float4 inTexWeights: TEXCOORD1) { MultiTexVertexToPixel Output = (MultiTexVertexToPixel)0; float4x4 preViewProjection = mul (xView, xProjection); float4x4 preWorldViewProjection = mul (xWorld, preViewProjection); Output.Position = mul(inPos, preWorldViewProjection); Output.Normal = mul(normalize(inNormal), xWorld); Output.TextureCoords = inTexCoords; Output.LightDirection.xyz = -xLightDirection; Output.LightDirection.w = 1; Output.TextureWeights = inTexWeights; Output.Depth = Output.Position.z; return Output; } struct MultiTexPixelToFrame { float4 Color : COLOR0; }; MultiTexPixelToFrame MultiTexturedPS(MultiTexVertexToPixel PSIn) { MultiTexPixelToFrame Output = (MultiTexPixelToFrame)0; float lightingFactor = 1; //To support detailed textures float blendDistance = 30; float blendWidth = 50; float blendFactor = clamp((PSIn.Depth-blendDistance)/blendWidth, 0, 1); if (xEnableLighting) lightingFactor = saturate(saturate(dot(PSIn.Normal, PSIn.LightDirection)) + xAmbient); float4 farColor; farColor = tex2D(SandTextureSampler, PSIn.TextureCoords)*PSIn.TextureWeights.x; farColor += tex2D(GrassTextureSampler, PSIn.TextureCoords)*PSIn.TextureWeights.y; farColor += tex2D(RockTextureSampler, PSIn.TextureCoords)*PSIn.TextureWeights.z; farColor += tex2D(SnowTextureSampler, PSIn.TextureCoords)*PSIn.TextureWeights.w; float4 nearColor; float2 nearTextureCoords = PSIn.TextureCoords*3; nearColor = tex2D(SandTextureSampler, nearTextureCoords)*PSIn.TextureWeights.x; nearColor += tex2D(GrassTextureSampler, nearTextureCoords)*PSIn.TextureWeights.y; nearColor += tex2D(RockTextureSampler, nearTextureCoords)*PSIn.TextureWeights.z; nearColor += tex2D(SnowTextureSampler, nearTextureCoords)*PSIn.TextureWeights.w; Output.Color = farColor*blendFactor + nearColor*(1-blendFactor); Output.Color *= saturate(lightingFactor + xAmbient); return Output; } technique MultiTextured { pass Pass0 { VertexShader = compile vs_1_1 MultiTexturedVS(); PixelShader = compile ps_2_0 MultiTexturedPS(); } } //--------------generate a shadow map------------------- sampler ColoredTextureSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = mirror; AddressV = mirror; }; //constants Texture xShadowMap; //Texture xCarLightTexture; sampler ShadowMapSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter = LINEAR; mipfilter=LINEAR; AddressU = clamp; AddressV = clamp; }; /* sampler CarLightSampler = sampler_state { texture = ; magfilter = LINEAR; minfilter=LINEAR; mipfilter = LINEAR; AddressU = clamp; AddressV = clamp; }; */ //------- Technique: ShadowMap -------- struct SMapVertexToPixel { float4 Position :POSITION; float3 Position2D :TEXCOORD0; }; struct SMapPixelToFrame { float4 Color :COLOR0; }; SMapVertexToPixel ShadowMapVertexShader( float4 inPos : POSITION) { SMapVertexToPixel Output = (SMapVertexToPixel)0; float4x4 preLightWorldViewProjection = mul (xWorld, xLightViewProjection); Output.Position = mul(inPos, preLightWorldViewProjection); Output.Position2D = Output.Position; return Output; } SMapPixelToFrame ShadowMapPixelShader(SMapVertexToPixel PSIn) { SMapPixelToFrame Output = (SMapPixelToFrame)0; Output.Color = PSIn.Position2D.z/xMaxDepth; return Output; } technique ShadowMap { pass Pass0 { VertexShader = compile vs_2_0 ShadowMapVertexShader(); PixelShader = compile ps_2_0 ShadowMapPixelShader(); } } //--------------Draw the shadow on the screen //------- Technique: ShadowedScene -------- struct SSceneVertexToPixel { float4 Position : POSITION; float4 ShadowMapSamplingPos : TEXCOORD0; float4 RealDistance : TEXCOORD1; float2 TexCoords : TEXCOORD2; float3 Normal : TEXCOORD3; float3 Position3D : TEXCOORD4; float4 Position2D : TEXCOORD5; }; struct SScenePixelToFrame { float4 Color : COLOR0; }; SSceneVertexToPixel ShadowedSceneVertexShader( float4 inPos : POSITION, float2 inTexCoords : TEXCOORD0, float3 inNormal : NORMAL) { SSceneVertexToPixel Output = (SSceneVertexToPixel)0; float4x4 preLightWorldViewProjection = mul (xWorld, xLightViewProjection); float4x4 preCameraWorldViewProjection = mul (xWorld, xCameraViewProjection); Output.Position = mul(inPos, preCameraWorldViewProjection); Output.ShadowMapSamplingPos = mul(inPos, preLightWorldViewProjection); Output.RealDistance = Output.ShadowMapSamplingPos.z/xMaxDepth; Output.Normal = normalize(mul(inNormal, (float3x3)xWorld)); Output.Position3D = mul(inPos, xWorld); Output.Position2D = Output.Position; Output.TexCoords = inTexCoords; if (xUseBrownInsteadOfTextures) Output.TexCoords = (0,0); return Output; } /*float DotProduct(float4 LightPos, float3 Pos3D, float3 Normal) { float3 LightDir = normalize(LightPos - Pos3D); return dot(LightDir, Normal); }*/ SScenePixelToFrame ShadowedScenePixelShader(SSceneVertexToPixel PSIn) { SScenePixelToFrame Output = (SScenePixelToFrame)0; float2 ProjectedTexCoords; ProjectedTexCoords[0] = PSIn.ShadowMapSamplingPos.x/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f; ProjectedTexCoords[1] = -PSIn.ShadowMapSamplingPos.y/PSIn.ShadowMapSamplingPos.w/2.0f +0.5f; float4 ColorComponent = tex2D(ColoredTextureSampler, PSIn.TexCoords); if ((saturate(ProjectedTexCoords.x) == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords.y) == ProjectedTexCoords.y)) { float StoredDepthInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).x; if ((PSIn.RealDistance.x - 1.0f/100.0f) <= StoredDepthInShadowMap) { float DiffuseLightingFactor = DotProduct(xLightPos, PSIn.Position3D, PSIn.Normal); Output.Color = ColorComponent*DiffuseLightingFactor*xLightPower; } } float2 screenPos; screenPos[0] = PSIn.Position2D.x/PSIn.Position2D.w/2.0f +0.5f; screenPos[1] = -PSIn.Position2D.y/PSIn.Position2D.w/2.0f +0.5f; for (int currentLight = 0; currentLight < 2; currentLight++) { float4 Light2DPos = mul(xLampPostPos[currentLight],xCameraViewProjection); float2 LightScreenPos; LightScreenPos[0] = Light2DPos.x/Light2DPos.w/2.0f +0.5f; LightScreenPos[1] = -Light2DPos.y/Light2DPos.w/2.0f +0.5f; float dist = distance(screenPos, LightScreenPos); float radius = 3.5f/distance(xCameraPos, xLampPostPos[currentLight]); if (dist < radius) { Output.Color.rgb += (radius-dist)*8.0f; } } Output.Color += ColorComponent * xAmbient; return Output; } technique ShadowedScene { pass Pass0 { VertexShader = compile vs_2_0 ShadowedSceneVertexShader(); PixelShader = compile ps_2_0 ShadowedScenePixelShader(); } }