Sign in to follow this  
dgroth

Another deferred shadow mapping problem

Recommended Posts

dgroth    100
Hello, Once again I have to reach out to you gurus. It must be a simple problem, and as with all simple problems, it only takes a second pair of eyes. My light matrix is wrong. When I pickup the depth in the shadow map the texture coordinates are sometimes outside the geometry (which should be impossible right?) So here is how I go about it: When render the shadow maps I store the distance from the light's camera to the vertex, like this: Vertex shader: vec4 E = gl_ModelViewMatrix * gl_Vertex; mDepth = length(E.xyz); gl_Position = gl_ProjectionMatrix * E; Fragment shader: gl_FragColor = vec4(mDepth, 0, 0, 1.0); For the above, the camera is from the light's position. The light's position is an arbitrary position along the direction of the light, placed in such a way that both the main camera and the light's camera can see the same objects. Both camera's have the same FOV etc... only positions and target are different. For the main rendering stream, I first do an early-Z pass (gBuffer0 below). Nothing fancy. I re-use the shader above to store the distance of the vertices to the camera (which is the main camera this time). Now, for the pre-lighting pass, I draw a quad from (0,0) to (1,1) and I re-construct the vertex position by setting up ray from the camera's position spanning the view screen from -1 to +1 Vertex shader: gl_Position.xy = gl_Vertex.xy * 2.0 - 1.0; gl_Position.zw = vec2(-1.0, 1.0); mEyeScreenRay = vec3(gl_Position.x * uAspectRatio, gl_Position.y, uNegInvTanHalfFOV); mTexCoord = gl_Vertex.xy; Fragment shader: gBuffer0 = texture2D(uGBuffer0, mTexCoord); E = mEyeScreenRay * gBuffer0.x; float distanceToLight = distance(E, uLightPosition.xyz); Then I take E and multiply that by the light's matrix and fetch what depth this vertex has seen from the light: vec4 shadowTexCoord = uLightMatrix * vec4(E, 1.0); shadowTexCoord = shadowTexCoord / shadowTexCoord.w; float occluderToLight = texture2D(uShadowTexture, shadowTexCoord.xy).x; I then determine if the vertex is in the shadow: shadow = 1.0; if (occluderToLight <= distanceToLight) shadow = 0.5; gl_FragColor = vec4(vec3(shadow), 1.0); There are a couple of uniforms I pass to the shaders that are worthwhile mentioning. First the light's position multiplied by the main camera transform: mLightPrePassProgram->set("uLightPosition", mCamera->getModelView() * vec4(lightDir->getPosition(), 1.0)); and, mLightPrePassProgram->set("uLightMatrix", lightDir->getLightMatrix()); The light matrix is calculated as follows: camera = cameras->get("Main"); mCamera = cameras->get("LightCamera"); mLightMatrix = mat4::IDENTITY; Given that the vertex (E) that will be multiplied by this matrix is re-construction the depth, it has already by multiplied by the gl_ModelViewMatrix, so I start by pushing an inverse camera transform: mLightMatrix *= camera->getInvModelView(); Now that we're back in a pre-model-view space, I push the light's camera transforms: mLightMatrix *= mCamera->getModelView(); mLightMatrix *= mCamera->getProj(); Then the usual * 0.5 + 0.5: mLightMatrix *= mat4::UNIT; Note: The order of my matrix multiplications above is "backward" - I know this, but so is my math code, so it ends up being the correct order in the end. I thought that writing down these steps would help me discover the flaw, but no. So, in advance thank you for your help in this matter. Regards, Dan.

Share this post


Link to post
Share on other sites
dgroth    100
Ok, got it.

With this method of re-constructing E, the depth has to be stored as:

mDepth = -E.z;

Now everything is cool. My lighting is also much better obviously... :)

And thanks for reading.

Oh, and while we're at it. I'd really like to move the light matrix mul outside the pixel shader and into the vertex shader, and also not bother about reconstructing E. So would't it be possible to transform the quad of view screen of the main camera into its corresponding "shape" in the light space, then just walk along that transformed quad to pick up the occluder depth in the shadow map ? I mean, there must be an advantage to doing deferred shadow mapping. I just haven't figured that one out yet. Any suggestions ?

Regards, Dan.

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