struct fragment { // normalized screen position float4 pos: WPOS; float4 texCoord: TEXCOORD0; float3 view: COLOR0; }; struct pixel { float4 color: COLOR0; }; #define NUM_SAMPLES 16 float2 myreflect(float2 pt, float2 n) { // distance to plane float d = dot(n, pt); // reflect around plane float2 rpt = pt - d * 2.0f * n; return rpt; } /** function for standard deferred shading */ float4 shade(fragment IN, uniform float4 color, uniform float4 position, uniform float3 normal, uniform float amb, float3 lightDir) { /* float4 lightDir2 = float4(-0.5f, 0.5f, 0.4f, 0.0f); float3 light2 = normalize(lightDir2.xyz); float diffuseLight2 = saturate(dot(normal, light2)); */ // diffuse intensity const float angle = saturate(dot(normal, lightDir)); float4 lightDiffuse = glstate.light[0].diffuse; float4 diffuse = angle * lightDiffuse; // global ambient const float4 ambient = glstate.light[0].ambient; return (ambient + diffuse) * color * (1.0f - amb) + amb * color; } /** The mrt shader for standard rendering */ pixel main(fragment IN, uniform sampler2D colors, uniform sampler2D positions, uniform sampler2D normals, uniform float3 lightDir ) { pixel OUT; float4 norm = tex2D(normals, IN.texCoord.xy); float4 color = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0)); float4 position = tex2D(positions, IN.texCoord.xy); // an ambient color term float amb = norm.w; float3 normal = normalize(norm.xyz); float4 col = shade(IN, color, position, normal, amb, lightDir); OUT.color = col; OUT.color.w = color.w; return OUT; } float CalcShadowTerm(fragment IN, uniform sampler2D shadowMap, uniform float w, uniform float2 lightSpacePos, uniform float depth, uniform float2 samples[NUM_SAMPLES], uniform sampler2D noiseTexture ) { //float shadowDepth = tex2D(shadowMap, lightSpacePos).x; //return step(depth, shadowDepth); float total_d = 0.0; for (int i = 0; i < NUM_SAMPLES; ++ i) { const float2 offset = samples[i]; #if 1 //////////////////// //-- add random noise: reflect around random normal vector (warning: slow!) float2 mynoise = tex2D(noiseTexture, IN.texCoord.xy).xy; const float2 offsetTransformed = myreflect(offset, mynoise); #else const float2 offsetTransformed = offset; #endif // weight with projected coordinate to reach similar kernel size for near and far float2 texcoord = lightSpacePos + offsetTransformed * w; float shadowDepth = tex2D(shadowMap, texcoord).x; total_d += step(depth, shadowDepth); } total_d /= (float)NUM_SAMPLES; return total_d; } pixel main_shadow(fragment IN, uniform sampler2D colors, uniform sampler2D positions, uniform sampler2D normals, uniform sampler2D shadowMap, uniform float4x4 shadowMatrix, uniform float maxDepth, uniform float sampleWidth, uniform sampler2D noiseTexture, uniform float2 samples[NUM_SAMPLES], uniform float3 lightDir ) { pixel OUT; float4 norm = tex2D(normals, IN.texCoord.xy); float4 color = tex2Dlod(colors, float4(IN.texCoord.xy, 0, 0)); float4 position = tex2D(positions, IN.texCoord.xy); const float3 normal = normalize(norm.xyz); // hack: an emmisive color term float emmisive = norm.w; // diffuse intensity const float angle = saturate(dot(normal, lightDir)); //float4 lightDiffuse = float4(1.0f, 1.0f, 0.9f, 1.0f); float4 lightDiffuse = glstate.light[0].diffuse; //float4(1.0f, 1.0f, 0.9f, 1.0f); float4 diffuse = lightDiffuse * angle; // calc diffuse illumination + shadow term if ((emmisive < 0.95f) // hack: prevent shadowing the sky && (angle > 1e-3f) // shadow only if diffuse color has some minimum intensity ) { position *= maxDepth; position.w = 1.0f; float4 lightSpacePos = mul(shadowMatrix, position); lightSpacePos /= lightSpacePos.w; float shadowTerm = CalcShadowTerm(IN, shadowMap, sampleWidth, lightSpacePos.xy, lightSpacePos.z, samples, noiseTexture); diffuse *= shadowTerm; } // global ambient //const float4 ambient = 0.25f; const float4 ambient = glstate.light[0].ambient; // base lighting OUT.color = (ambient + diffuse) * color * (1.0f - emmisive) + emmisive * color; // also write out depth component OUT.color.w = color.w; return OUT; }