shadowmapping texture coordinates in shader
I request assistance in getting my texture coordinates correct. I think that is part of the the problem I have with my shadow mapping code. My current result shows no shadows, just a dithering everywhere.
In my first pass, I move the GL camera to the same position as the light. I render the scene to a texture and it uses a shader to save the depth from the camera (aka light). Here is core code for the depth saving shader
vec4 viewPos = gl_ModelViewMatrix * gl_Vertex;
float depth = (length(viewPos)-near_clip)/(far_clip-near_clip);
gl_FrontColor.r = depth;
gl_Position = ftransform();
I view this texture in a pwindow and it looks like I would expect it to look. I think this step in the process is ok.
Also on this 1st pass, I use a JS sketch to save the matrix needed to later index into the texture w/ depth data. Here’s core code:
//texture scale-bias matrix
sketch.gltranslate(0.5, 0.5, 0.5);
sketch.glscale(0.5, 0.5, 0.5);
sketch.gluperspective(light_lens_angle, 1.0, light_near_clip, light_far_clip);
sketch.glulookat(light_pos, light_pos, light_pos,
light_lookat, light_lookat, light_lookat,
up, up, up);
matrix = sketch.glget("modelview_matrix");
On my 2nd pass, I move the camera to my desired location. I then render the scene using a phong shader with added shadow mapping. This shader works correctly with the phong shading. Its when I add my buggy shadowmapping code that it fails. I bind the texture w/ the depth data on to the OB3D objects. I also pass the matrix calculated above in JS (called lightToTex) into this 2nd shader. In the vertex shader, this is the shadow specific code:
varying vec4 shadowtexCoord0;
varying float dist;
uniform mat4 lightToTex;
curPos = gl_ModelViewMatrix * gl_Vertex;
dist = length(gl_LightSource.position.xyz - curPos.xyz);
shadowtexCoord0 = lightToTex * gl_Vertex;
In the fragment shader the shadow specific code is:
varying vec4 shadowtexCoord0; // Used for shadow lookup
varying float dist;
uniform sampler2D tex0;
float shadowdepth = texture2DProj(tex0, shadowtexCoord0).r;
float normdist = (dist-near_clip)/(far_clip-near_clip); // normalize current distance by near/far clip as as the depth shader at the top
float shadowval = (normdist > shadowdepth) ? 0.5 : 1.0;
gl_FragColor = color * vec4(shadowval, shadowval, shadowval, 1.0);
very interesting! i am keeping my fingers crossed for your research! :)
I tried making shadows a while ago, and did exactly the same thing as you.
(Computing the transformation matrix and passing it into the shader)
The missing clue was the: Inverse Viewmatrix of the camera to get the sm coordinates right.
A helpful resource hereby was a pdf called "SM_RTR.pdf". It’s the top hit on google.
(Adding the direct link seems to be a problem)
You can also have a look at my attempt here:
I only did the transformation matrix with lua, as I do not speak java.
You can have a look at it inside the "TransformationMatrices" subpatcher.
Thanks, mark2e. I am closer to success; I can occasionally see some somewhat correct shadows but the majority of the shadow mapped space is in shadow from something big and seems to relate to the camera. Logic or code bugs remain for me to squash.
I had previously convinced myself that I can just use a saved matrix multiplication of the 1st pass (bias * perspective * glulookat) against the 2nd pass fragment being rendered. That was wrong; you are correct. The nugget of info that I didn’t understand was that when I retrieve gl_ModelViewMatrix in the 2nd pass vertex shader, that OpenGL has already combined the current primitive’s Model *and* the current camera View into a single gl_ModelViewMatrix. I wrongly thought the camera’s simulated movement (that inverse you can get from glulookat) was combined within the Projection matrix (it’s not).
gluperspective -> projection matrix
glulookat -> camera’s contribution into the modelview matrix
gltranslate,scale,rotate -> model’s contribution into the modelview matrix
So to isolate just the 2nd pass primitive’s Model matrix, I need the inverse of the 2nd pass’s camera’s View (aka its contribution into the 2nd passes modelview matrix). That should get the matrix stack back to just the Model of the 2nd pass vertex which I can then transform with the previously saved matrix from pass 1.
Do you agree with this thinking?
Sounds like it would work.
I got the inverse cameraview matrix from the anim.node connected to the camera. (gettransform or getinvtransform)
Then matrix-multiplied (inside or before the shader)
vec4 tempPos = gl_ModelViewMatrix * gl_Vertex; //Pass2 Transform.
tempPos = InvVmatrix * tempPos; //Multiplied with the inverse viewmatrix. Which was my missing clue.
ShadowC = MVPmatrix * tempPos; //Then the transformation matrix from pass1 => shadowmap texture coordinates.
Which seems to work.
Most times I had was glitchy stuff on screen. I had with the wrong order of multiplying the matrices. ^^