Skip to main content
GameDev.net gamedev.net
🔒 Locked

Odd GLSL shadow mapping problem

Started by elias4444 Mar 21, 2009 at 2:02 PM 3 replies 2.7k views
Original Post
elias4444
elias4444
Ok, I have shadow mapping working perfectly using the fixed-function pipeline. I use glTexGen with GL_EYE_LINEAR on GL_S, GL_T, GL_R, GL_Q, etc.. Only problem is though, that to use shaders, I have to do shadow mapping in the shader as well. I think I've officially found and tried every single GLSL shadow mapping tutorial and code bit that can be found online. And the ones I could get to work, all end up having the same issue: my shadows aren't projected correctly. The following is a simple scene using plain opengl without any shaders: Software Shadow Map It works great. The following is the same scene rendered using the shadow mapping shaders from the opengl orange book: Shader Shadow Mapping I haven't blended anything with the base textures yet, since I want to solve the shadow mapping problem first. But, as you can see, the shadows aren't being projected properly. And I've run into this same projection problem with every other GLSL shadow mapping shader I've gotten to "work." My guess is that it has something to do with how I'm setting up and creating the shadow map texture, but I fail to see why my method would work with the plain-opengl method and not a shader method? I've tried fiddling with my light's matrices and perspective without any luck so far. About the only thing I haven't been able to try is a non-power-of-two texture for the shadowmap to match the screen resolution (when I try that, my machine just freezes for some reason). Still, I don't understand why it works fine when not using shaders. Any ideas? Code examples? A possible tutorial I haven't found yet? ANY help is greatly appreciated! I've been stuck on this for a while now. [Edited by - elias4444 on March 22, 2009 2:36:16 PM]
elias4444
elias4444
For an update (and a shameless bump), I've noticed that when moving the walls and other objects in the scene, the shadows don't change on the object. It appears that the shadowmap is being mapped to each object individually.

Also, for reference, here is the shader code I'm using (it's right out of the Orange Book):

//// Vertex Shader ////////attribute float Accessibility;varying vec4  ShadowCoord;  // Ambient and diffuse scale factors.const float As = 1.0 / 1.5;const float Ds = 1.0 / 3.0;void main(){    vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;    vec3 ecPosition3 = (vec3(ecPosition)) / ecPosition.w;    vec3 VP = vec3(gl_LightSource[0].position) - ecPosition3;    VP = normalize(VP);    vec3 normal = normalize(gl_NormalMatrix * gl_Normal);    float diffuse = max(0.0, dot(normal, VP));    float scale = min(1.0, Accessibility * As + diffuse * Ds);    vec4 texCoord = gl_TextureMatrix[1] * gl_Vertex;    ShadowCoord   = texCoord / texCoord.w;    gl_FrontColor  = vec4(scale * gl_Color.rgb, gl_Color.a);    gl_Position    = ftransform();}//// Fragment Shader //////uniform sampler2DShadow ShadowMap;uniform float Epsilon;varying vec4 ShadowCoord;float lookup(float x, float y){    float depth = shadow2DProj(ShadowMap,                      ShadowCoord + vec4(x, y, 0, 0) * Epsilon).x;    return depth != 1.0 ? 0.75 : 1.0;} void main(){    float shadeFactor = lookup(0.0, 0.0);    gl_FragColor = vec4(shadeFactor * gl_Color.rgb, gl_Color.a);}


Also, here is my code for setting up the matrices:

	private void recalcMatrix() {		if (useFBOs || usePBuffer) {			GL11.glMatrixMode(GL11.GL_PROJECTION);			GL11.glPushMatrix();			GL11.glLoadIdentity();			GL11.glOrtho(-(float)shadowMapSize/2f, (float)shadowMapSize/2f, -(float)shadowMapSize/2f, (float)shadowMapSize/2f, 10f, 5000f);			projectionMatrix.clear();			GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrix);			GL11.glPopMatrix();			GL11.glMatrixMode( GL11.GL_MODELVIEW );			GL11.glPushMatrix();			GL11.glLoadIdentity();			Vector3f position = light.getPosition();			Vector3f lookAt = light.getLookAt();			GLU.gluLookAt(position.x, position.y, position.z,					lookAt.x, lookAt.y, lookAt.z,					0.0f, 1f, 0.0f );			viewMatrix.clear();			GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, viewMatrix);						GL11.glPopMatrix();		}	}	private void bindShadowMap() {		if (useFBOs || usePBuffer) {			GL11.glEnable( GL11.GL_LIGHTING );			GL11.glMatrixMode(GL11.GL_TEXTURE);			GL13.glActiveTexture(GL13.GL_TEXTURE1);			GL11.glBindTexture(GL11.GL_TEXTURE_2D, shadowTextureID); 						GL11.glEnable(GL11.GL_TEXTURE_2D);			sX.rewind();			sY.rewind();			sZ.rewind();			sW.rewind();			GL11.glTexGen( GL11.GL_S, GL11.GL_EYE_PLANE, sX );			GL11.glTexGen( GL11.GL_T, GL11.GL_EYE_PLANE, sY );			GL11.glTexGen( GL11.GL_R, GL11.GL_EYE_PLANE, sZ );			GL11.glTexGen( GL11.GL_Q, GL11.GL_EYE_PLANE, sW );			biasMatrix.rewind();			GL11.glLoadMatrix(biasMatrix);			projectionMatrix.rewind();			GL11.glMultMatrix(projectionMatrix);			viewMatrix.rewind();			GL11.glMultMatrix(viewMatrix);						GL11.glMatrixMode(GL11.GL_MODELVIEW);		}	}
NumberXaero
NumberXaero
Try something smaller for ortho instead of half the buffer dimensions, something like 6 - 12, what happens?
elias4444
elias4444
It basically just cuts off the shadowmap and extends the edges to "infinity." The screenshot below is with shadowMapSize/12f instead of shadowMapSize/2f:

Smaller Ortho

elias4444
elias4444
Ok, problem solved.

For those who stumble on this thread (or in case I forget), the trick is that you have to call all of your translate, rotate, and scale methods for the texture matrix as well as your modelview matrix when using shaders. Of course, you DON'T want to do that if you're using the opengl fixed-function-pipeline (makes testing the two side-by-side kind of tricky).

Thanks to those who helped!!!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.