Shadow mapping on a Geforce 2 + Nvidia "Shadowcast" demo

Started by
19 comments, last by godmodder 17 years, 11 months ago
Hello, I just started trying to experiment with shadows of some sort, and I wanted to start with shadow mapping. I have a Geforce 4 MX and I just realised that you need a Geforce 3 or up for the depth comparison to be done in hardware (shadow mapping demos run at < 0.1 fps). How is the realtime shadow generated in a game like Hitman 3 (which I was playing today on my computer)? I don't know much about various shadow techniques, but from the aliasing it seems like it is shadow mapping. Take a look: Free Image Hosting at www.ImageShack.us /edit: changed the title [Edited by - deavik on May 2, 2006 2:58:21 AM]
Advertisement
They use 8-bit shadowmapping or 16-bit register combiner dual texture shadowmapping. There's a tutorial on how to implement these techniques on:
http://www.paulsprojects.net/opengl/shadowmap/shadowmap.html

They're only practical if you apply them to very few objects in your scene (like only hitman) and the aliasing and artifacts will be severe for large distances. So, it's your call...

Hope I've been able to help you,
Jeroen
Thanks, that was a great link!

When you say "They're only practical if you apply them to very few objects in your scene", do you mean because they are more expensive to do than regular shadowmapping?

I haven't had time to look through what's going on in the demo yet - just a disclaimer.
Check out this. As long as you don't plan on continually updating the shadow maps, that method'll work fine. By the way, as long as you're rendering to the entire colour buffer (sky box/dome when outside, all 4 walls, a floor and a roof when inside, etc.), you can ignore the whole clearing the colour buffer bit.
Gorax, thanks for the link. Your vertex shader looks very attractive, but I'll try it a bit later. Right now I'm trying to implement the "dual texture" method given in the later half of this paper by Mark Kilgard.

Firstly, does anyone have a copy of the "Shadowcast" demo with source code which is mentioned at the end of that paper? I searched and searched, but it seems like NV have taken it off the developer website. I'm having a hard time figuring out how to do the matrix math for the texgen modes.

Secondly, I have a little problem with copying the depth buffer with glReadPixels as mentioned in that paper. If I copy into an array of ubytes (as suggested in the paper) all the values are 255 (I checked). So, If I create a texture out of this data (call glTexImage2D with data format LUMINANCE and type UNSIGNED_BYTE) I get a white texture.

In a strange manner, it works as it should and I can see the depth buffer if I copy the depth buffer as 16bit ushorts, then supplying that to glTexImage2D as 2 ubytes per texel (luminance + alpha). ie:
	GLushort data[SHADOW_MAP_SIZE * SHADOW_MAP_SIZE];	glReadPixels(0, 0, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, data);	glTexImage2D(GL_TEXTURE_2D, 0, GL_INTENSITY8, SHADOW_MAP_SIZE, SHADOW_MAP_SIZE, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data);
If you want Hitman style shadows, you don't actually need to do any depth rendering or depth comparison. The Hitman games just render the characters from the lights point of view into a normal texture (render the character without textures as a single black/grey colour) then use that texture to project from the lights point of view.

There's no self shadowing in the game so there is no depth comparing.
Quote:Original post by deavik
If I copy into an array of ubytes (as suggested in the paper) all the values are 255 (I checked).


This is because of the extremely limited depth buffer precision afforded by the 8-bit shadow map. In my shadow mapping demo (link already posted by godmodder), you can use the arrow keys to adjust the size of the frustum - note how the shadows go wrong once the near clip plane is closer to the camera than 0.3 or so. At this point, due to the non-linear nature of the depth buffer, many of the values are 255.

In other words, you need to push your near clip plane (when drawing from the light's POV) as far out as possible.
Quote:Original post by bakery2k1
This is because of the extremely limited depth buffer precision afforded by the 8-bit shadow map. In my shadow mapping demo (link already posted by godmodder), you can use the arrow keys to adjust the size of the frustum - note how the shadows go wrong once the near clip plane is closer to the camera than 0.3 or so. At this point, due to the non-linear nature of the depth buffer, many of the values are 255.

In other words, you need to push your near clip plane (when drawing from the light's POV) as far out as possible.

bakery2k1, I didn't know that website was yours! From the looks of it, you've got some great demos there! [smile]

Back to my problem, you were spot on with the depth precision - moving the near plane out solved the problem. Now, after that (and looking through your code) I've got the depth map in properly, but after that I'm having trouble projecting it.

OK depth map:


But if I try the projective texturing I get little "shadowed" streaks, and excepth that nothing:
Free Image Hosting at www.ImageShack.us

When you are multiplying with the bias matrix the light projection and view matrices, how do you obtain the latter two? At the moment I just save the matrices from when I capture the depth from the light's point of view:

// set up projection and look-at from light's point of view
glGetFloatv(GL_PROJECTION_MATRIX, light_proj);
glGetFloatv(GL_MODELVIEW_MATRIX, light_view);

Is this correct? Thanks for any help!
Try performing the projective texturing with the depth map alone - without performing the shadow comparison. What does that look like?

Quote:
When you are multiplying with the bias matrix the light projection and view matrices, how do you obtain the latter two? At the moment I just save the matrices from when I capture the depth from the light's point of view:

// set up projection and look-at from light's point of view
glGetFloatv(GL_PROJECTION_MATRIX, light_proj);
glGetFloatv(GL_MODELVIEW_MATRIX, light_view);


That should work, but note that you need the light's "view" matrix, not the "modelview". You need to make sure that you are getting the matrices before performing any model transformations.
bakery2k1, first of all thanks for sticking with me. After a lot of experimentation, I reversed the order of your matrix multiplies and it gives me this:

Free Image Hosting at www.ImageShack.us

Note that this is just with the depth texture (no tex_env_combine and no depth ramp texture either). It looks about alright, but then I am stuck at the next stage - combining with the depth ramp texture. This is what it looks like when I try it:

Free Image Hosting at www.ImageShack.us

With your wizard-like diagnostic skills [smile], can you suggest what I am doing wrong?

The paper by MJK states "save the depth map as INTENSITY8" which is what I am doing. I don't exactly yet know how tex_env_combine works - but it's specifying the texture as a source of ALPHA. Does that mean the texture's internal format has to be ALPHA?

If you suspect a particular portion of the code tell me I will post it.

This topic is closed to new replies.

Advertisement