Hi! I'm working on a graphics project, and I wanted to add simple shadows to it.
I tried to do shadow mapping like in
Shadow Mapping Tutorial, but it didn't exactly work.
I'm basically having 2 different problems:
1) This seems to be an ATi only problem. As soon as I enable shadowing (e.g. render to a depth map and use it), performance drops to about 3-4 FPS. Otherwise it's smooth (no FPS counter, but it's at least 30 FPS, since there are no lags). Funny thing is, the same happens when I use that tutorial's example - a trivial scene at 5 FPS.
This all happened on my X800 GTO2. Then I tested it on nVidia's 6600GT, and it works just fine - tutorial's example at 100FPS, and mine quite smooth.
I tried different texture filtering (nearest/linear/mipmap), different Z-buffer depths (16/24/32), different depth map depths (16/24/32/default), and nothing helped - same 3-4 FPS. Seems like copying to the depth map takes huge amount of time.
Here's what I use now:
// Initialize depth texture (my texture loader, basically sets the passed params)
if (!glTex::UseTex(NULL, DepthSize, DepthSize, TexDepth, GL_DEPTH_COMPONENT, GL_LINEAR_MIPMAP_LINEAR, GL_CLAMP_TO_EDGE)) return false;
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_ALPHA);
// Update depth texture
glBindTexture(GL_TEXTURE_2D, TexDepth);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, DepthSize, DepthSize);
I should note that I'm not using pbuffers/FBO - only glCopyTexSubImage2D. I know that's inefficient, but FBOs are only available on new hardware, and pbuffers aren't that easy to work with. But this shouldn't be the problem since I'm also using cube mapping, and that is 6 copies. If cube mapping works fast, why shadow mapping doesn't?
(Just in case, I updated the drivers - no change)
Did anyone have this problem before? I've only seen similar drop in performance when I used NPOT textures with mipmaps on ATi (again, nVidia didn't seem to care).
Could this be remedied by using pbuffers?
If anyone has an ATi card, please try to download the demo of the tutorial and tell the FPS you get (it could be due to my computer/driver/card combo).
2) This problem is unrelated, and is actually about the algorithm. In the tutorial, only back faces are rendered to the depth map. I cannot do that since I have non-closed (flat) objects in my scene. So what I do is render whole scene, same way, and use polygon offset.
Now when rendering, I tried to render bright first, shadowed second, but eventually used the opposite (with depth test of GL_LESS). This is because I have alpha blending in the scene (the grass), and it produced weird bright spots because bright didn't overwrite dark but combined with it.
Here's how I render:
// Snap shadow map
SnapDepth(TexDepth);
// Go to reflective object position and snap cubemap
glLoadTransposeMatrixd((double*)RefObjMat);
SnapCubemap(TexCubemap);
// Draw objects (bright light)
glLoadTransposeMatrixd((double*)CameraViewMat);
glAlphaFunc(GL_GEQUAL, 0.01f);
glEnable(GL_ALPHA_TEST);
DrawObjects();
glDisable(GL_ALPHA_TEST);
// Draw objects (dim light)
glDepthFunc(GL_LESS);
glLoadTransposeMatrixd((double*)CameraViewMat);
DrawObjects(3);
glDepthFunc(GL_LEQUAL);
First shadowed, then bright almost works. The problem can be seen in the following screenshot:
First image is camera view, second is light view. Object is a concave mirror. In camera view, you can see the weird bright strip between 2 shadowed parts. That is between shadow due to lighting model (opposite side to light) and shadow due to shadow mapping (self-shadowing). Reversing bright/dark render order didn't change anything regarding that strip.
I guess that the reason for it is either imprecision (512*512 depth map, maybe 2K*2K could fix that, but that's too big), or polygon offset (moving shadow back a bit). I can't remove polygon offset because then whole scene would be Z-fighting.
Any ideas how to fix it, leaving the mirror completely flat? (A solution is making it a shape with volume, but that's not what I want)
P.S. shadow looks rather ugly, any way to improve that without using shaders? (OpenGL 1.4 only). I know nVidia has some kind of PCF built in and enabled through GL_LINEAR filter, but it doesn't seem to work on ATi.
Thanks in advance!