Orange Book Shadow Maps Vertex Shader

I am having a small problem with the vertex shader for shadow maps as described in the Orange Book section 13.2.2


//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()
{
	float Accessibility = 0.0;
    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; //<- here

    gl_FrontColor  = vec4(scale * gl_Color.rgb, gl_Color.a);
    gl_Position    = ftransform();
}

This is the vertex shader as shown in the book.

It says that is is dividing this:
ShadowCoord = texCoord / texCoord.w; //<- here
to get perspective-correct projective texture coordinates and save having to do the divide on the fragment shader. however with this line left as it is, my shadows show incorrectly where as changing it to
ShadowCoord = texCoord;
makes them display correctly, albeit with plently of artifacts which is to be expected I believe.

The Fragment shader is also just as the book describes. and I construct gl_TextureMatrix[1] as

gl_TextureMatrix[1] = bias_matrix * light_modelview_matrix * light_projection_matrix;

on the application side.

is there any really obvious mistake I could be making? I checked the deLight demo’s shaders (shadow_prologue.vert/frag i believe)on which this Vertex shader was based, it also doesn’t do the division by w.

thanks for any help or suggestions.

I’ma sorry for bumping this, but here is the fragment shader, which I forgot to include:


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);
}

I don’t have the answers you want, as I never did shadow mapping myself. But comparing the shaders to my projective texturing method I have an idea what may be going on.
The fragment shader is using shadow2DProj which AFAIK does the division for you.
You can try to do the division in the vertex shader (as the original code does) and use shadow2D instead of shadow2Dproj in the fragment shader.

Thank you for the suggestion, you are right that shadow2DProj divides through by the tex-coord’s q component (according to the Orange Book)

However leaving the Vertex shader in it’s original form and changing the Fragment shader’s lookup() function to use shadow2D doesn’t solve my problem.

It’s interesting to note that the Orange Book gives two subsequent Fragment shaders (in Listing 13.6 and 13.7, for generating anti-aliased edges) which are based on the one I posted above, however the lookup() function uses shadow2D and it does not explain the reason for the switch.

Could this be a mistake in the book? or maybe I am misreading somewhere and the 1 vertex and 3 fragment shaders they supplied for use in shadow mapping are not supposed to be used together?

Or I’m making a mistake in my source elsewhere :s

I’ll have to think about this tomorrow.

Have you checked the book’s errata page?

i just checked the book errata (http://3dshaders.com/home/index.php?option=com_content&task=view&id=14&Itemid=28) and did not find anything mentioned about the issue being discussed.