Sign in to follow this  
Synthesizer

Deferred Rendering + Shadow Map

Recommended Posts

Synthesizer    188
Hello, I have recently implemented deferred rendering (from Catalin Zima's example) because of a performance problem with forward rendering with more than 1 light. During the last month I've been reading Riemer's Shadow Map example and I finally understood the concept. Now I'm trying to implement it for one directional light. I've created an orthogonal Projection Matrix & a View Matrix for the light. But I can't figure out how to convert each vertex to 2d texture coordinate: In forward, in your VS you convert each vertex to 2d Screen Space as seen by the light by multiplying the position per WorldViewProjection matrix. Then in the PS you map it to Texture Coordinate, check if this point is included in the ShadowMap texture, & if so, u get the depth stored on it. But in deferred, all your scene is previously rendered in textures. In the PS Catalin gets the position like this:
[source code="C#"]
    //read depth
    float depthVal = tex2D(depthSampler,input.TexCoord).r;

    //compute screen-space position
    float4 position;
    position.x = input.TexCoord.x * 2.0f - 1.0f;
    position.y = -(input.TexCoord.x * 2.0f - 1.0f);
    position.z = depthVal;
    position.w = 1.0f;
    //transform to world space
    position = mul(position, InvertViewProjection);
    position /= position.w;

so I tried multiplying this position per LightsViewProjection matrix & then project to texture coords, but it didn't work. I really don't know what to do... I've spent many hours & days, read ShadowMap forward rendering examples (XNA Creators, Riemer) & MJP's Deferred Cascaded Shadow Map (I don't understand it). Could you please help me? Thank you very much!

Share this post


Link to post
Share on other sites
Shirakana2    500
As soon as you can reconstruct your world space position properly, the shadow map stuff is the same as usual.

BTW I don't understand the "position /= position.w;" ? Isn't this division already included in your matrix ?

Share this post


Link to post
Share on other sites
Synthesizer    188
Hi Shirakana2,

-position is the result of the multiplication between a vector and a 4x4 Matrix. We cannot use their components immediately, so we need to divide them by the homogeneous one (w) (anyway I tried your suggestion: it makes fog look better, but the specular is for some reason disabled... I have no idea why this happens).

-Apart from this things: I try to understand the logic of what I'm doing & I think I'm getting the correct worldspace position: evrth is drawn fine. I get some shadows but they are not correct. You can see the results here

and here is my full Pixel Shader:

[source code="C#"]
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
//get normal data from the normalMap
float4 normalData = tex2D(normalSampler,input.TexCoord);
//tranform normal back into [-1,1] range
float3 normal = 2.0f * normalData.xyz - 1.0f;
//get specular power, and get it into [0,255] range]
float specularPower = normalData.a * 255;
//get specular intensity from the colorMap
float specularIntensity = tex2D(colorSampler, input.TexCoord).a;

//read depth
float depthVal = tex2D(depthSampler,input.TexCoord).r;

//compute screen-space position
float4 position;
position.x = input.TexCoord.x * 2.0f - 1.0f;
position.y = -(input.TexCoord.y * 2.0f - 1.0f);
position.z = depthVal;
position.w = 1.0f;
//transform to world space
position = mul(position, InvertViewProjection);
position /= position.w;

//fog (if i comment the line above the fog looks better, more dense, but models are drawn like in an ambient light or so only):
float d = length(position - cameraPosition);
float l = saturate((d-fog.near)/(fog.far-fog.near));


//surface-to-light vector
float3 lightVector = -normalize(lightDirection);



//float4x4 viewToLightViewProj=mul(InvertViewProjection,LightsViewProjection);
//float4 Pos2DAsSeenByLight=mul(lightVector,viewToLightViewProj);
float4 Pos2DAsSeenByLight=mul(position,LightsViewProjection);


float2 ProjectedTexCoords;
ProjectedTexCoords[0] = Pos2DAsSeenByLight.x/Pos2DAsSeenByLight.w/2.0f +0.5f;
ProjectedTexCoords[1] = -Pos2DAsSeenByLight.y/Pos2DAsSeenByLight.w/2.0f +0.5f;

//compute diffuse light

float diffuseLightingFactor = 0;
if ((saturate(ProjectedTexCoords).x == ProjectedTexCoords.x) && (saturate(ProjectedTexCoords).y == ProjectedTexCoords.y))
{
float depthStoredInShadowMap = tex2D(ShadowMapSampler, ProjectedTexCoords).r;
float realDistance = Pos2DAsSeenByLight.z/Pos2DAsSeenByLight.w;
if ((realDistance - 1.0f/100.0f) <= depthStoredInShadowMap)
{
diffuseLightingFactor = max(0,dot(normal,lightVector));
diffuseLightingFactor = saturate(diffuseLightingFactor);
}
}


//float NdL = max(0,dot(normal,lightVector));
//float3 diffuseLight = NdL * Color.rgb;
float3 diffuseLight = diffuseLightingFactor * Color.rgb;

//reflexion vector
float3 reflectionVector = normalize(reflect(-lightVector, normal));
//camera-to-surface vector
float3 directionToCamera = normalize(cameraPosition - position);
//compute specular light
float specularLight = specularIntensity * pow( saturate(dot(reflectionVector, directionToCamera)), specularPower);

//output the two lights
//return lightIntensity * float4(diffuseLight.rgb, specularLight) ;

//return lerp(lightIntensity * float4(diffuseLight.rgb, specularLight), fog.color, l);
return lerp(lightIntensity * float4(diffuseLight.rgb, specularLight), fog.color, l);
}



I'm very very new to shaders & as in many cases, it's a 1 man project where I try to do evrth, even the models (the guy is me :))
So well, I'll be very thankful if u could help me with a concept, with any correction or whatever!

Synth

Share this post


Link to post
Share on other sites
Shirakana2    500
I'm not really friendly with HLSL language and DirectX convention but I would make a few remark:

"float3 normal = 2.0f * normalData.xyz - 1.0f;"
=> you should renormalize it: you lose precision when storing normal into texture so there's no guarantee that normal is normalized after reading it back.

"position = mul(position, InvertViewProjection);"
=> I would invert the parameter order: position = mul(InvertViewProjection,position);
Remember that M*v != v*M and that could make the difference

"float4 Pos2DAsSeenByLight=mul(position,LightsViewProjection);" => same remark as above

"diffuseLightingFactor = saturate(diffuseLightingFactor);" if lightVector is normalized, you don't need this line

[Edited by - Shirakana2 on May 3, 2010 10:55:11 AM]

Share this post


Link to post
Share on other sites
Synthesizer    188
Thank you very much Shirakana2!
I added the normalizing & even though I inverted the multiplications, shadows doesn't show up. But when inverting the position multiplication, fog works better (even though there is no specular, like when commenting "position /= position.w;").

So for the moment I'll leave it the way it is, with fog looking good, because as u get closer to a point light, the character gets brighter & the specular (from point light) appears (u can see it here). So it gives a nice look :)

I think I'll leave shadows apart for the moment, until I learn a bit more & manage to do it right! But it's looking rather nice, so thank you for your help!

Synth

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this