ShadowMapping: Shadows only visible at y=0

hello,
i have implemented shadowmapping with an FBO and GLSL.
it is used on a heightfield. that is some objects (trees, plants, …) cast shadows on the heightfield.

the problem i have, is that the shadows are only visible on the ground of the heightfield. that is, where the heightfield’s height = 0. as soon as there is some height involved, the shadows disappear. if i look at the shadowmap itself, everything looks fine… objects that are closer to the light are darker.

here is my GLSL code:


uniform mat4 lightView, lightProjection;

const mat4 biasMatrix = mat4(	0.5, 0.0, 0.0, 0.0,
								0.0, 0.5, 0.0, 0.0,
								0.0, 0.0, 0.5, 0.0,
								0.5, 0.5, 0.5, 1.0);	//bias from [-1, 1] to [0, 1]

void main()
{	
	gl_Position = ftransform();	
		
	mat4 shadowMatrix = biasMatrix * lightProjection * lightView;
	shadowTexCoord = shadowMatrix * gl_Vertex;    
}


uniform sampler2DShadow shadowmap;
varying vec4 shadowTexCoord;

void main() 
{    
    vec4 shadow = shadow2DProj(shadowmap, shadowTexCoord, 0.0);
    float colorshadow = shadow.r < 0.1 ? 0.5 : 1.0;

vec4 color = vec4(1,1,1,1);	

	gl_FragColor = vec4( color*colorshadow, color.w );	
}


thanks a lot for any help on this!

(bump)

i am still having this problem. btw: shadows are there on objects that are below height 0 too. so it is not just at height 0 but on anything below 0 but not above 0.

thanks for any help!


const mat4 biasMatrix = mat4( 0.5, 0.0, 0.0, 0.0,
			      0.0, 0.5, 0.0, 0.0,
			      0.0, 0.0, 0.5, 0.0,
			      0.5, 0.5, 0.5, 1.0);	

That looks suspect. You should transpose the matrix before using it.

thanks for your reply!

if i transpose it, it looks like this right?


const mat4 biasMatrix = mat4(	0.5, 0.0, 0.0, 0.5,
				0.0, 0.5, 0.0, 0.5,
				0.0, 0.0, 0.5, 0.5,
				0.0, 0.0, 0.0, 1.0);	//bias from [-1, 1] to [0, 1]

anyways, this results in no shadows at all :frowning:

You should also check if the lightView and lightProjection matrices are correct. gl_Vertex is treated as a column vector, so matrix elements should be set in the column major order.

thanks for your reply.
well the matrices are pretty much what i get from
glGetFloatv(GL_PROJECTION_MATRIX) in the shadowpass.

in detail my shadowpass setup looks like this:


	glClearColor(1,1,1,1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushAttrib(GL_VIEWPORT_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	int const size = 50;
	glOrtho(-size, size, -size, size, 1.0, 100.0);
	
	
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	gluLookAt(	myp.lx+10, myp.ly+40, myp.lz+10, 
				myp.lx, myp.ly, myp.lz, 
				0, 1, 0); // light view matrix
	
	glViewport(0, 0, sm_size, sm_size);

	glGetFloatv(GL_PROJECTION_MATRIX, lpm);
	glGetFloatv(GL_MODELVIEW_MATRIX, lvm);

Oops! Actually you were right, the bias matrix you set at the beginning is the right one, as elements are set in column major order as I said :slight_smile: So once the matrix content written, it looks like the transpose one. Sorry, no more idea for now!

Realizing that you are using the shadow2DProj built-in function, did you set correctly the depth comparison mode to the depth texture? Something like:


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL);

thanks!

yes these two parameters are set to the depth texture.

the really strange thing is, that shadows are visible on anything that is below the height of zero (y<0) in the scene. but anything above it, does not have shadows, although everything looks fine in the shadowmap itself.

(bump)

could it be, that i forgot to integrate the transformations into the shadowtexcoords? because after thinking about this for a while, it seems that the shadowcoords do not respect the place, rotation and scaling of the objects.

could it be, that i forgot to integrate the transformations into the shadowtexcoords?

What transformations are you talking about? Shadowmap texture coordinates are the projection of the scene from the light point of view.

yes, but they also need to take care of the glRotates, glScales, glTranslates, etc, right?

because now it seems that the shadows on the objects do not respect that.

for example: i have an object casting a shadow on a wheel.
as long as the wheel does have no transformations, the shadows look fine. but as soon, as i start to rotate the wheel, the shadows move with the wheel, as if it was just another multitexture.

thanks!

You mean that if you render the scene without applying any transformation to objects, shadows are correctly casted?
In that case, yes your transformation matrix setup is probably wrong.

You probably already understand that, but I just wan’t to make it clear. You have to distinguish several types or transformations:

  • Model ( also known as World)
  • View
  • Projection

The World transformation transforms scene entities from object space (proper to the object) to World space and it is used to describe the distribution of all scene objects.
The View transformation just move the World space origin to the camera one in respect of its position and orientation.

When you render from the light or from the camera point of view the World matrix must be the same since the light and the camera are in the same space, the world space. World transformation may be modeled with glTranslate, glRotate calls but have to be the same depending on whether you render from light or from camera.

The only difference in transformation matrix setup is about the view and projection transformations.

exactly! that is the problem!

thanks for the explanation, but how can i fix my problem?

but how can i fix my problem?

Did you read the next paragraph? If you use some glTranslate and glRotate calls to place your objects in the scene world. You have to do the same depending on whether you draw from the light or the camera point of view.

thanks,
well, actually i think i already do this. it is basically like this:

  1. set camera to lightpos
  2. render scenegraph
  3. copy depthbuffer to texture (shadowmap)
  4. set camera normal
  5. render scenegraph (with shader)

the "render scenegraph"s contains some translations, but they contain exactly the same translations each time it is called.

Ok, so now I do not understand your concern in your last post:

yes, but they also need to take care of the glRotates, glScales, glTranslates, etc, right?

Since apparently it is handled in the scenegraph.

yes, the scenegraph handles the transformations.
but what i mean is, that maybe i have to apply these transformations by hand in the shader in order to create the shadowtexcoords?

for example providing a

uniform mat4 modelTransform;

for each object and multiplying that into the shadowtexcoords like this:

mat4 shadowMatrix = biasMatrix * lightProjection * lightView * modelTrans;
shadowTexCoord = shadowMatrix * gl_Vertex;

mat4 shadowMatrix = biasMatrix * lightProjection * lightView * modelTrans;

If LightView contains the view transformation that moves from World space to Light space and modelTrans, the World transformations applied on the rendered object then, yes this is what I was trying to tell you.

One question, in one of the code samples you posted here I noticed that you set Orthogonal projection, is it still the case?

thanks!

yes, it still is a orthogonal projection for the lightsource-pass, since i try to simulate sunlight.