shadow mapping (texture matrix gen)

i’m working on an implementation of shadow mapping using fixed pipe exts. I just would like to get (again) some more infos concerning the generation of the texture matrix.

when constructing this matrix using scale * bias *lightFrustumMatrix * lightViewMatrix what is exactly the light modelview used ?

searching around it is still not clear for me.
Is it the light modelview matrix which is used to construct the light frustum (while generating the depthmap using either gluPerspective(…) and/or glFrustum(…) ?

Or is this the light modelview generated after from the eye view for normal scene rendering pass?

thx

Texgen happens in eye space or object space.

When you apply the frustum it will project based on vertex locations in those spaces. You can set your plane equations to anything but let’s assume they’re at the origin and axis aligned.

Now, if you use object space texgen the light will be in a different location for every object under transformation unless you shadow the model matrix on the texture matrix stack, this is the wrong thing to do but I’ve done it in the past.

http://www.sgi.com/software/performer/brew/aqua.html#_cch3_886491683

The smarter way to do this is texgen in eyespace, however to stop the texgen following the eye and position it in a fixed position in worldspace, you need to load the inverse viewing matrix onto the texture matrix stack to position the texgen in the world. The frustum multiplication on the matrix stack is a way of defining the field of view of the light projection and dividing s & t by r. Instead of this frustum matrix you can texgen q instead which will result in a projection effect due to the homogeneous divide.

http://www.sgi.com/software/performer/brew/uav.html#_cch3_887222955

allright, i’m doing texgen in eye-space but i’m stuck with the final tranformations tu set up texture coordinates (shodow map) in the 2nd pass…

Maybe it’s a little bit tricky due to my engine design on top of GL. In fact, i do all the tranformations on my own then the modelview is set to the appropriate matrix (loadMatrix) for each displayed primitive.

That means, that there is no viewing matrix inside of (only identity). Thus, only the projection matrix is evaluated by openGL.

As at has no incidence when rendering the scene from the light or any camera, the shdow map is rendered properly but in this case, what should be the correct equation? bcoz using idendity matrix (modelview) and setting up eye-planes is something different from most of the examples i can find around about shadow mapping.

Nvida docs about the subject got:

Epo = SB * P(light) * invM(light)* V

Then i’ve taken only the 2 first components to test with and see what was going on and then using:

Epo = SB * P(light)

a kind of light frustum appear with the depthmap inside of it… but not projected as it should be.

stuck & lost -> Ozzy ^^

Ok, finally i’ve done the right stuff concerning the opengl matrix stacks and it has solved many of my probs. Thus here i’m using : scaleBias * lightFrustum * lightViewMatrix.

But there is still a problem when rotating the light (same position), the frustum looks ok but the projected depthmap representing the character doesn’t seem to move at all. (it moves only when translating the light btw).

you can check and give me some hint about that
(2 != (rotated light) views with corresponding depthmaps)
following this link:
http://snow.prohosting.com/ozzyyzzo/

thx for any help

Shadows don’t change when you rotate the light.

That’s right… ^^

But why it is doing this when i’m using:
SB * lightFrustum * lightModelview ?
It just works like if it was a point light generating shadows… (thus shadows are only moving when tralating the light).

On the other hand, when all the scene is mapped with the depthmap using:
SB * cameraFrustum * lightModelview
i got nice results with rotations etc but of course it fails when using the compare func for real shadows. :-/

anyone?

I’m sorry, I still don’t get the problem. From what you describe, it sounds like you’re getting the correct results. Spotlights are nothing but pointlights with everything outside the cone masked out. Hence rotating a spotlight doesn’t affect the shadows unless they get outside the cone of influence. The shadow map obviously changes a lot as the light’s projection changes, but the shadows really shouldn’t.

Perhaps you can achieve the effect you’re looking for by moving the light around the object, keeping it always pointed at the object?

-Ilkka

Allright… it works like this then.
thank you for this detail.

now i would like to implement a shadow_ambient like (ext which is not available on my FX5200).

Thus i saw from the shadowCast example from nvidia the func:

configCombinersForHardwareShadowPass(int withTexture)
{
glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, 2);
glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, lightDimColor);
glCombinerParameterfvNV(GL_CONSTANT_COLOR1_NV, Ka);

/* Argb = one /
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_A_NV,
GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
/
Brgb = constant0rgb = light dimming /
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_B_NV,
GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
Crgb = 1.0 - constant0rgb = 1.0 - light dimming /
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_C_NV,
GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_INVERT_NV, GL_RGB);
/
Drgb = texture0rgb = unshadowed percentage */
glCombinerInputNV(GL_COMBINER0_NV, GL_RGB, GL_VARIABLE_D_NV,
GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);

/* spare0rgb = light dimming + (1.0 - light dimming) * unshadowed percentage */
glCombinerOutputNV(GL_COMBINER0_NV, GL_RGB,
GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);

/* Discard entire Alpha combiner stage 0 */
glCombinerOutputNV(GL_COMBINER0_NV, GL_ALPHA,
GL_DISCARD_NV, GL_DISCARD_NV, GL_DISCARD_NV,
GL_NONE, GL_NONE,
GL_FALSE, GL_FALSE, GL_FALSE);

/* Argb = spare0rgb = light dimming + (1.0 - light dimming) * unshadowed percentage /
glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_A_NV,
GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
Brgb = primary color = light’s diffuse contribution /
glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_B_NV,
GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
Crgb = constant 1 = Ka = ambient contribution /
glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_C_NV,
GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
Drgb = 1 */
glCombinerInputNV(GL_COMBINER1_NV, GL_RGB, GL_VARIABLE_D_NV,
GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);

/* spare0rgb =
(light dimming + (1.0 - light dimming) * unshadowed percentage) * diffuse +
ambient */
glCombinerOutputNV(GL_COMBINER1_NV, GL_RGB,
GL_DISCARD_NV, GL_DISCARD_NV, GL_SPARE0_NV,
GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE);

/* Discard entire Alpha combiner stage 1 /
glCombinerOutputNV(GL_COMBINER1_NV, GL_ALPHA,
GL_DISCARD_NV, GL_DISCARD_NV, GL_DISCARD_NV,
GL_NONE, GL_NONE, GL_FALSE, GL_FALSE,
GL_TRUE); /
Use the MUX operation. */

if (withTexture) {
/* A = texture1 = decal /
glFinalCombinerInputNV(GL_VARIABLE_A_NV,
GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
} else {
/
A = one /
glFinalCombinerInputNV(GL_VARIABLE_A_NV,
GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB);
}
/
B = spare0 /
glFinalCombinerInputNV(GL_VARIABLE_B_NV,
GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
C = zero /
glFinalCombinerInputNV(GL_VARIABLE_C_NV,
GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
E = unshadowed percentage /
glFinalCombinerInputNV(GL_VARIABLE_E_NV,
GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
F = specular /
glFinalCombinerInputNV(GL_VARIABLE_F_NV,
GL_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
D = EF product = unshadowed percentage * specular contribution /
glFinalCombinerInputNV(GL_VARIABLE_D_NV,
GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB);
/
RGB = A*B + (1-A)*C + D = (texture1 OR 1) * space0 + specular * unshadowed */

/* G = 1 /
glFinalCombinerInputNV(GL_VARIABLE_G_NV,
GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA);
/
Alpha = 1 */

glEnable(GL_REGISTER_COMBINERS_NV);

//…

which use the depthmap in unit0.

Ok, i’m not really familiar with combiners so is it possible to modify this function when the depthmap is binded in the last unused texture unit? eg: unit0 is used with a texture and unit1 is the depthmap or unit0 and unit1 are textures and unit2 is the depthmap and so on… ?