PDA

View Full Version : Shadow mapping



debonair
03-28-2013, 03:48 AM
Hi,
I read some tutorials on shadow mapping and implementing a simple program for it. But i am getting some weird output. Here is my code:
I am copying here minimal code:



render_to_depth()
{
A_VECTOR from[]={5,2,-2};
A_VECTOR at[]={0,0,0};
A_VECTOR up[]={0,1,0};
A_MATRIX mvp_matrix, mv_matrix, normal_matrix, projection_matrix, camera_matrix, model_matrix,temp_matrix;
AMatrixIdentity(&camera_matrix);

AMatrixIdentity(&model_matrix);
AMatrixCreateViewMatrixLH(&camera_matrix,from,at,up,1.0);


AMatrixTranslate(&model_matrix, 0.0f, -2.0f, 0.0f);

AMatrixMultiply(&mv_matrix, &model_matrix, &camera_matrix);
AMatrixIdentity(&projection_matrix);
//nResult |= AMatrixPersp(&projection_matrix, 60.0f, (float)GetViewportWidth()/GetViewportHeight(), 2.0f, 100.0f);
nResult |= AMatrixOrtho(&projection_matrix,-10,10,-10,10,-10,20);
//nResult |= AMatrixOrtho(&projection_matrix,-6,6,-6,6,-6,12);
AMatrixMultiply(&temp_matrix, &camera_matrix, &projection_matrix);
light_mvp=temp_matrix;
AMatrixMultiply(&mvp_matrix, &mv_matrix, &projection_matrix);
glEnable(GL_DEPTH_TEST);

glViewport(0, 0, GetViewportWidth(),GetViewportHeight());


glColorMask(0.0f,0.0f,0.0f,1.0f);

glClearDepth(1.0f);

glClear(GL_DEPTH_BUFFER_BIT);
for(int i=0;i<6;i++)
{
glDrawArrays (GL_TRIANGLE_FAN, i*4, 4);
}

}
create_depth_texture()
{
glGenTextures(1, &depth_texture);
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_2D, depth_texture);

glGenRenderbuffers(1, &m_colorBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);
nResult |= GL_ERROR_CHECK((GL_NO_ERROR, "glBindRenderbuffer(GL_RENDERBUFFER, m_colorBuffer);"));
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, 32, 32);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer);

glUniform1i(glGetUniformLocation(shader_data.psId,"tk_shadowMap"), 7);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT32, GetViewportWidth(),GetViewportHeight(), 0,GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,depth_texture,0) ;
}
main()
{

create_depth_texture();
A_VECTOR from[]={0,5,-10};
A_VECTOR at[]={0,0,0};
A_VECTOR up[]={0,1,0};
AMatrixIdentity(&camera_matrix);


// AMatrixCreateViewMatrixLH(&camera_matrix,from,at,up,1.0);

AMatrixIdentity(&model_matrix);
AMatrixRotate(&model_matrix, ((GLES_Pi/4)), ((GLES_Pi/4)), 0.0f);
AMatrixTranslate(&model_matrix, 0.0f, 0.0f, -2.0f);
AMatrixMultiply(&mv_matrix, &model_matrix, &camera_matrix);

nResult |= AShaderGetUniformLocation(shader_data, "tk_mvMatrix", &modelViewProjectionMatrix);
glUniformMatrix4fv(modelViewProjectionMatrix, 1, GL_FALSE, &mv_matrix._11);

AMatrixIdentity(&projection_matrix);
AMatrixMultiply(&mvp_matrix, &mv_matrix, &projection_matrix);

nResult |= AShaderGetUniformLocation(shader_data, "tk_mvpMatrix", &modelViewProjectionMatrix);
glUniformMatrix4fv(modelViewProjectionMatrix, 1, GL_FALSE, &mvp_matrix._11);

AMatrixIdentity(&normal_matrix);
AMatrixInvertTranspose(&normal_matrix, &mv_matrix);

glUniformMatrix4fv(modelViewProjectionMatrix, 1, GL_FALSE, &normal_matrix._11);
glUniformMatrix4fv(modelViewProjectionMatrix, 1, GL_FALSE, &light_mvp._11);
glActiveTexture(GL_TEXTURE0);

glBindTexture(GL_TEXTURE_2D, id1);

glActiveTexture(GL_TEXTURE7);

glBindTexture(GL_TEXTURE_2D, depth_texture);

for(int i=0;i<6;i++)
{
glDrawArrays(GL_TRIANGLE_FAN,i*4,4);
}

}



Vertex shader:



in vec3 tk_position;
in vec3 tk_texCoord;
in vec3 tk_normal;

out vec2 ps_texCoord;
out vec4 ps_shadowCoord;
out vec3 ps_lightDir;
out vec3 ps_normal;
out vec3 ps_eyeVec;

uniform mat4 tk_mvMatrix;
uniform mat4 tk_mvpMatrix;
uniform mat4 tk_normalMatrix;
uniform mat4 light_mvp;
uniform mat4 biasMatrix;

uniform vec3 tk_lightPos;

void main()
{

//tk_normal=normalize(tk_position);
ps_normal = (tk_normalMatrix * vec4(tk_normal, 1.0)).xyz;

vec4 ePos = tk_mvMatrix * vec4(tk_position, 1.0);
vec4 eLight = tk_mvMatrix * vec4(tk_lightPos, 1.0);
ps_lightDir = normalize(eLight.xyz - ePos.xyz);

ps_eyeVec = -ePos.xyz;

ps_texCoord = tk_texCoord.st;

ps_shadowCoord = biasMatrix* light_mvp * ePos;

gl_Position = tk_mvpMatrix * vec4(tk_position, 1.0);
}


Fragment shader


in vec2 ps_texCoord;
in vec3 ps_lightDir;
in vec3 ps_normal;
in vec3 ps_eyeVec;
in vec4 ps_shadowCoord;

uniform vec4 tk_ambientColor;
uniform vec4 tk_diffuseColor;
uniform vec4 tk_specularColor;

uniform sampler2D tk_diffuseMap;
uniform sampler2D tk_shadowMap;

out vec4 fragColor;

void main()
{

float shadow = 1.0f;


highp float comp = (ps_shadowCoord.z / ps_shadowCoord.w);
highp float depth = texture2DProj(tk_shadowMap, ps_shadowCoord).r;

shadow = comp <= depth ? 1.0 : 0.4;


float diffuseIntensity = max(0.0, dot(normalize(ps_normal), normalize(ps_lightDir)));
vec3 color = shadow * (diffuseIntensity * tk_diffuseColor.rgb) * texture(tk_diffuseMap, ps_texCoord.st).rgb;

fragColor = vec4(color, 1.0);



}

995

Dark Photon
03-28-2013, 05:50 AM
... i am getting some weird output. Here is my code...
What have you tried to diagnose it? Do you have any specific technical questions? Do you understand the technique?

debonair
03-28-2013, 06:43 AM
Thanks for your reply.
I am rendering the cube in depth texture and i want the shadow of the cube on below platform.

What have you tried to diagnose it?

I tried by changing light positions and projection to ortho (currently it is perspective) while rendering to depth texture. but it did not work.


Do you have any specific technical questions? Do you understand the technique?

I am not sure whether i understood it or not as my output is not as per expected.
When i do not rotate my platform (rectangle below cube) as well as cube, the whole cube goes into the shadow in the image shown.

Dark Photon
03-28-2013, 06:14 PM
Try "lowp vec3 color = texture2D(sTexture, texCoord).rgb;" to eliminate the other terms as a potential cause.

How sure are you that the light source is above the plane on the eye's side of the plane?

I would double-check the code that's computing TexProjectionMatrix.

Also, flip to an Ortho light projection (i.e. directional light) for starters. You also don't need texture2DProj for that, just texture2D (though it shouldn't hurt).

debonair
03-29-2013, 12:49 AM
Try "lowp vec3 color = texture2D(sTexture, texCoord).rgb;" to eliminate the other terms as a potential cause.

How sure are you that the light source is above the plane on the eye's side of the plane?

I would double-check the code that's computing TexProjectionMatrix.

Also, flip to an Ortho light projection (i.e. directional light) for starters. You also don't need texture2DProj for that, just texture2D (though it shouldn't hurt).

Really sorry, i had posted wrong shaders. Now corrected it in my first post..
Can you please check the shaders above?

Dark Photon
03-29-2013, 01:33 PM
Vertex shader:
...
vec4 ePos = tk_mvMatrix * vec4(tk_position, 1.0);
ps_shadowCoord = biasMatrix* light_mvp * ePos;
...


That sure doesn't look right. ePos is your position in the camera's EYE-SPACE. light_mvp takes you from the light's OBJECT-SPACE to the light's CLIP-SPACE. light_mvp sure ends up in the right space, but it doesn't start in camera's EYE-SPACE like you need it to if you're going to feed ePos into it.

You need to get your space transforms right. Study the first diagram on this page:

* Shadow Mapping (Paul's Projects) (http://www.paulsprojects.net/tutorials/smt/smt.html)

Also your C++ transform code doesn't make much sense to me. You need to separate your "camera" transform path from your "light" transform path.

If we get rid of all the syntax fluff, here's what I think you have:


camera = IDENTITY;
model = IDENTITY;
camera = VIEWING( from,at,up,1.0 );
model = TRANSLATE( 0, -2, 0 );
mv = model * camera;
projection = IDENTITY;
projection = ORTHO( -10,10,-10,10,-10,20 );
temp = camera * projection;
light_mvp = temp;
mvp = mv * projection;


Why are you using the same projection transform for both light and camera? Why are you using the same viewing transform for both light and camera? Why does light_mvp not have a modeling transform?

debonair
04-01-2013, 06:32 AM
That sure doesn't look right. ePos is your position in the camera's EYE-SPACE. light_mvp takes you from the light's OBJECT-SPACE to the light's CLIP-SPACE. light_mvp sure ends up in the right space, but it doesn't start in camera's EYE-SPACE like you need it to if you're going to feed ePos into it.

You need to get your space transforms right. Study the first diagram on this page:

* Shadow Mapping (Paul's Projects) (http://www.paulsprojects.net/tutorials/smt/smt.html)


I have modified my transformations, but still i am getting weird o/p

For light view: pass 1:


from[]={2,2,-2};
at[]={0,0,0};
up[]={0,1,0};
createview_matrix(&camera_matrix,from,at,up,1.0)

translate_matrix(&model_matrix, -2.0f, 0.0f, -2.0f);

mv_matrix=model_matrix*camera_matrix
MatrixOrtho(&projection_matrix,-10,10,-10,10,-10,20);
mvp_matrix=mv_matrix*projection_matrix;
light_mvp=mv_matrix;


Pass 2, camera view:


from[]={4,2,-2};
at[]={2,0,0};
up[]={0,1,0};
createview_matrix(&camera_matrix,from,at,up,1.0)
model_matrix=translate(0.0f, 2.0f, -2.0f)
mv_matrix=model_matrix*camera_matrix;
Persp(&projection_matrix, 45.0f, (float)GetViewportWidth()/GetViewportHeight(), 0.1f, 100.0f);
mvp_matrix=mv_matrix*projection_matrix



Shaders are same. Previously light_mvp had contained projection matrix of light now it has only model and view matrix.

Now i am getting shadow on half of cube and plane (if we see in y-axis), but i want lighted cube with shadow on platform