//----------------------------------------------------------------------------- // File: ShadowMap.fx // // Desc: Effect file for shadow mapping used // // started from DX 9.0c SDK shadowmap example // Holger Grahn hg .at.snafu.de //----------------------------------------------------------------------------- // size of shadow map for custom filtering #define SMAP_SIZE 1024 //#define SHADOW_EPSILON 0.00005f #define SHADOW_EPSILON 0.005f // state matrices float4x4 g_mWorld : WORLD; float4x4 g_mWorldView : WORLDVIEW; float4x4 g_mProj : PROJECTION; // textures texture baseTexture; // baisic diffuse texture for object texture shadowDepthTexture; // depth texture (i.e. R32F float texture) containing scene depth from light view float4x4 lightViewProjection; // Transform from world w space to light projection space //float4 materialDiffuseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); // diffuse material float3 lightPosition; // Light position in view space float3 lightDirection; // Light direction in view space float4 lightDiffuseColor = float4( 1.0f, 1.0f, 1.0f, 1.0f ); // Light diffuse color float4 lightAmbientColor = float4( 0.3f, 0.3f, 0.3f, 1.0f ); // Use an ambient light of 0.3 float lightSpotAngleCos; // Cosine of theta of the spot light // define material structure struct Material { // matches D3DMATERIAL9 float4 diffuseColor; float4 ambientColor; float4 specularColor; float4 emissiveColor; float power; }; struct Light { int type; // D3DLIGHTTYPE float4 diffuseColor; // D3DLIGHT9 float4 specularColor; float4 ambientColor; float3 position; float3 direction; float range; float falloff; float attenuation0; float attenuation1; float attenuation2; float theta; float phi; bool on; }; // our material, gets updated automatically from Contact because of MATERIAL semantic Material material : MATERIAL = { float4(1.0f, 0.0f, 1.0f, 1.0f), //diffuse float4(0.0f, 0.0f, 0.0f, 0.0f), //ambient float4(0.0f, 0.0f, 0.0f, 0.0f), //specular float4(0.0f, 0.0f, 0.0f, 0.0f), //Emissive 0.0 }; sampler2D g_samScene = sampler_state { Texture = ; MinFilter = Point; MagFilter = Linear; MipFilter = Linear; }; sampler2D g_samShadow = sampler_state { Texture = ; // Floating point texture can't be filtered yet on current hardware, arg MinFilter = Point; MagFilter = Point; MipFilter = Point; AddressU = Clamp; AddressV = Clamp; }; //----------------------------------------------------------------------------- // Vertex Shader: VertScene // Desc: Process vertex for scene //----------------------------------------------------------------------------- void VertScene( float4 iPos : POSITION, float3 iNormal : NORMAL, float2 iTex : TEXCOORD0, out float4 oPos : POSITION, out float2 Tex : TEXCOORD0, out float4 vPos : TEXCOORD1, out float3 vNormal : TEXCOORD2, out float4 vPosLight : TEXCOORD3 ) { // // Transform position to view space // vPos = mul( iPos, g_mWorldView ); // // Transform to screen coord // oPos = mul( vPos, g_mProj ); // // Compute view space normal // vNormal = mul( iNormal, (float3x3)g_mWorldView ); // // Propagate texture coord // Tex = iTex; // // Transform the position to light projection space, or the // projection space as if the camera is looking out from // the spotlight. // //vPosLight = mul( vPos, g_mViewToLightProj ); // we can't premult with view matrix vPosLight = mul( iPos, g_mWorld); vPosLight = mul( vPosLight, lightViewProjection ); } //----------------------------------------------------------------------------- // Pixel Shader: PixScene // Desc: Process pixel (do per-pixel lighting) for enabled scene //----------------------------------------------------------------------------- float4 PixScene( float2 Tex : TEXCOORD0, float4 vPos : TEXCOORD1, float3 vNormal : TEXCOORD2, float4 vPosLight : TEXCOORD3 ) : COLOR { float4 Diffuse; // vLight is the unit vector from the light to this pixel float3 vLight = normalize( float3( vPos - lightPosition ) ); // Compute diffuse from the light if ( dot( vLight, lightDirection ) > lightSpotAngleCos ) // Light must face the pixel (within Theta) { // Pixel is in lit area. Find out if it's // in shadow using 2x2 percentage closest filtering //transform from RT space to texture space. float2 ShadowTexC = 0.5 * vPosLight.xy / vPosLight.w + float2( 0.5, 0.5 ); ShadowTexC.y = 1.0f - ShadowTexC.y; // return tex2D( g_samShadow, ShadowTexC ); // diag: show depth // transform to texel space float2 texelpos = SMAP_SIZE * ShadowTexC; // Determine the lerp amounts float2 lerps = frac( texelpos ); float LightAmount; if (true) { //read in bilerp stamp, doing the shadow checks float sourcevals[4]; sourcevals[0] = (tex2D( g_samShadow, ShadowTexC ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; sourcevals[1] = (tex2D( g_samShadow, ShadowTexC + float2(1.0/SMAP_SIZE, 0) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; sourcevals[2] = (tex2D( g_samShadow, ShadowTexC + float2(0, 1.0/SMAP_SIZE) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; sourcevals[3] = (tex2D( g_samShadow, ShadowTexC + float2(1.0/SMAP_SIZE, 1.0/SMAP_SIZE) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; // lerp between the shadow values to calculate our light amount LightAmount = lerp( lerp( sourcevals[0], sourcevals[1], lerps.x ), lerp( sourcevals[2], sourcevals[3], lerps.x ), lerps.y ); } else { LightAmount = (tex2D( g_samShadow, ShadowTexC ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; } // Light it Diffuse = ( saturate( dot( -vLight, normalize( vNormal ) ) ) * LightAmount * ( 1 - lightAmbientColor ) + lightAmbientColor ) * material.diffuseColor; } else { Diffuse = lightAmbientColor * material.diffuseColor; } return Diffuse+material.emissiveColor; return tex2D( g_samScene, Tex ) * Diffuse; } //----------------------------------------------------------------------------- // Vertex Shader: VertLight // Desc: Process vertex for the light object //----------------------------------------------------------------------------- void VertLight( float4 iPos : POSITION, float3 iNormal : NORMAL, float2 iTex : TEXCOORD0, out float4 oPos : POSITION, out float2 Tex : TEXCOORD0 ) { // // Transform position to view space // oPos = mul( iPos, g_mWorldView ); // // Transform to screen coord // oPos = mul( oPos, g_mProj ); // // Propagate texture coord // Tex = iTex; } //----------------------------------------------------------------------------- // Pixel Shader: PixLight // Desc: Process pixel for the light object //----------------------------------------------------------------------------- float4 PixLight( float2 Tex : TEXCOORD0, float4 vPos : TEXCOORD1 ) : COLOR { return tex2D( g_samScene, Tex ); } //----------------------------------------------------------------------------- // Vertex Shader: VertShadow // Desc: Process vertex for the shadow map //----------------------------------------------------------------------------- void VertShadow( float4 Pos : POSITION, float3 Normal : NORMAL, out float4 oPos : POSITION, out float2 Depth : TEXCOORD0 ) { // // Compute the projected coordinates // oPos = mul( Pos, g_mWorldView ); oPos = mul( oPos, g_mProj ); // // Store z and w in our spare texcoord // Depth.xy = oPos.zw; } //----------------------------------------------------------------------------- // Pixel Shader: PixShadow // Desc: Process pixel for the shadow map //----------------------------------------------------------------------------- void PixShadow( float2 Depth : TEXCOORD0, out float4 Color : COLOR ) { // // Depth is z / w // Color = Depth.x / Depth.y; } //----------------------------------------------------------------------------- // Technique: RenderScene // Desc: Renders scene objects with shadow deptmap per pixel lighting //----------------------------------------------------------------------------- technique RenderScene { pass p0 { VertexShader = compile vs_1_1 VertScene(); PixelShader = compile ps_2_0 PixScene(); } } //----------------------------------------------------------------------------- // Technique: RenderShadow // Desc: Renders the shadow map //----------------------------------------------------------------------------- technique RenderShadow { pass p0 { VertexShader = compile vs_1_1 VertShadow(); PixelShader = compile ps_2_0 PixShadow(); } } //----------------------------------------------------------------------------- // Technique: RenderLight // Desc: Renders the light object //----------------------------------------------------------------------------- technique RenderLight { pass p0 { VertexShader = compile vs_1_1 VertLight(); PixelShader = compile ps_1_1 PixLight(); } }