PDA

View Full Version : Trying shadow mapping, yet everything is dark



A_Shuang
03-20-2015, 04:06 AM
I'm currently trying the shadow mapping with JOGL. I tried to render grass with shadow on it. But the result comes out to be that all the objects are dark. Here is my code:


//bind framebuffer for shadow mapping
gl.glGenFramebuffers(1, framebuff);
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));

gl.glGenTextures(1, textureBuff);

gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(0));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_DEPTH_COMPONENT32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_MODE, GL4.GL_COMPARE_REF_TO_TEXTURE);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_FUNC, GL4.GL_LEQUAL);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_DEPTH_ATTACHMENT, textureBuff.get(0), 0);
gl.glDrawBuffer(GL4.GL_NONE);
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, 0);


Here is the code calculating the shadowMatrix:


float[] sPmvMat = new float[16];

pmvMatrix.glLoadIdentity();
pmvMatrix.gluLookAt(100f, 100f, 100f, 0f, 0f, 0f, 0f, 1.0f, 0f);
pmvMatrix.glFrustumf(-1f, 1f, -1f, 1f, 1f, 100f);
pmvMatrix.multPMvMatrixf(sPmvMat, 0);

float[] scale_bias_Mat = {
0.5f, 0.0f, 0.0f, 0.0f,
0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, 0.5f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f
};

Matrix4 m = new Matrix4();
m.loadIdentity();
m.multMatrix(scale_bias_Mat);
m.multMatrix(sPmvMat);

shadowMat = m.getMatrix();



Here is the drawing command:


gl.glEnable(GL4.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(2.0f, 4.0f);

gl.glUseProgram(shaderProgram);

setMvpMatrix();
gl.glUniformMatrix4fv(shadowM_Loc, 1, false, shadowMat, 0);

gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(0));
gl.glViewport(0, 0, displayWidth, displayHeight);

gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
gl.glClearDepth(1.0f);

gl.glBindVertexArray(vaoBuff.get(0));
gl.glDrawArraysInstanced(GL4.GL_TRIANGLE_STRIP, 0, 5, 512 * 512);

gl.glDisable(GL4.GL_POLYGON_OFFSET_FILL);



Here is the vertex shader code:


"#version 430 \n" +
"layout (location = 3) uniform mat4 mvMatrix; \n" +
"layout (location = 4) uniform mat4 proMatrix; \n" +
"layout (location = 10) uniform mat4 shadowMat; \n" +
"layout (location = 0) in vec4 position; \n" +
"out VS_OUT \n" +
"{ \n" +
" vec4 shadowCoord; \n" +
"} vs_out; \n" +
" \n" +
"void main(void) \n" +
"{ \n" +
" randomize position... \n" +
" \n" +
" vs_out.shadowCoord = shadowMat * position; \n" +
" \n" +
" gl_Position = proMatrix * mvMatrix * position; \n" +
"}"


Here is the fragment shader code:


"#version 430 \n" +
"layout (binding = 0) uniform sampler2DShadow shadow_tex;\n" +
"out vec4 output_color; \n" +
"in VS_OUT \n" +
"{ \n" +
" vec4 shadowCoord; \n" +
"} fs_in; \n" +
"void main(void) \n" +
"{ \n" +
" output_color = textureProj(shadow_tex, fs_in.shadowCoord) * vec4(0.2, 0.7, 0.2, 1.0); \n" +
"}"




Added:
It seems I have found the reason. I added a line checking the framebuffer status after setting up that framebuffer. Yet it returns a wrong status (36054). Any ideas?
Here is the code:


//bind framebuffer for shadow mapping
gl.glGenFramebuffers(1, framebuff);
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));

gl.glGenTextures(1, textureBuff);

gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(0));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_DEPTH_COMPONENT32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR);//GL_LINEAR_MIPMAP_LINEAR
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_MODE, GL4.GL_COMPARE_REF_TO_TEXTURE);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_FUNC, GL4.GL_LEQUAL);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_DEPTH_ATTACHMENT, textureBuff.get(0), 0);
gl.glDrawBuffer(GL4.GL_NONE);

if(gl.glCheckFramebufferStatus(GL4.GL_FRAMEBUFFER) != GL4.GL_FRAMEBUFFER_COMPLETE)
return gl.glCheckFramebufferStatus(GL4.GL_FRAMEBUFFER);

Dark Photon
03-20-2015, 06:09 AM
Please surround code blocks with ... or [code]...[/nocode] blocks. It makes it much more readable, and improves your chance of someone sifting your post and giving you a helpful response. I've added them for you.

A_Shuang
03-20-2015, 07:13 AM
@Dark Photon Thanks for doing that.

Dark Photon
03-20-2015, 04:59 PM
Here is the code calculating the shadowMatrix:


...
Matrix4 m = new Matrix4();
m.loadIdentity();
m.multMatrix(scale_bias_Mat);
m.multMatrix(sPmvMat);

shadowMat = m.getMatrix();

...

Here is the vertex shader code:


...
vs_out.shadowCoord = shadowMat * position;
gl_Position = proMatrix * mvMatrix * position;
...



Your shadowMat transforms from world-space. But your vertex shader logic implies that position is both an object-space position and a world-space position? Which is it? (or is your modeling transform the identity)?


Here is the fragment shader code:


"#version 430 \n" +
"layout (binding = 0) uniform sampler2DShadow shadow_tex;\n" +
"out vec4 output_color; \n" +
"void main(void) \n" +
"{ \n" +
" output_color = textureProj(shadow_tex, fs_in.shadowCoord) * vec4(0.2, 0.7, 0.2, 1.0); \n" +
"}"


Any ideas?
This wouldn't have compiled. Are you abbreviating some of this?

Suggest you dump your transform matrices and make sure they look reasonable to you. Push some sample vector transforms through by paper to ensure you get what you think you should.

A_Shuang
03-20-2015, 09:16 PM
Still didn't figure it out.

I also tried to render the buffer depth from the light point of view.


//setting up buffers
gl.glGenFramebuffers(1, framebuff);
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));

gl.glGenTextures(2, textureBuff);
gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(0));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_R32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR_MIPMAP_LINEAR);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_COLOR_ATTACHMENT0, textureBuff.get(0), 0);

gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(1));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_DEPTH_COMPONENT32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR_MIPMAP_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_MODE, GL4.GL_COMPARE_REF_TO_TEXTURE);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_FUNC, GL4.GL_LEQUAL);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_DEPTH_ATTACHMENT, textureBuff.get(1), 0);



"#version 430 \n" +
"layout (location = 3) uniform mat4 mvMatrix; \n" +
"layout (location = 4) uniform mat4 proMatrix; \n" +
"layout (location = 0) in vec4 position; \n" +
" \n" +
"void main(void) \n" +
"{ \n" +
" randomize position... \n" +
" \n" +
" gl_Position = proMatrix * mvMatrix * position; \n" +
"}"



"#version 430 \n" +
"out vec4 output_color; \n" +
"void main(void) \n" +
"{ \n" +
" output_color = vec4(gl_FragCoord.z); \n" +
"}"



//gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));
gl.glViewport(0, 0, displayWidth, displayWidth);
/*IntBuffer frameType = GLBuffers.newDirectIntBuffer(1);
frameType.put(GL4.GL_COLOR_ATTACHMENT0);
gl.glDrawBuffers(1, frameType);
gl.glClearBufferfv(GL4.GL_COLOR, 0, new float[] {0, 0, 0}, 0);
gl.glClearDepth(1.0f);*/
setupMVPMatrix();
gl.glBindVertexArray(vaoBuff.get(0));
gl.glUseProgram(shaderProgram);
gl.glDrawArraysInstanced(GL4.GL_TRIANGLE_STRIP, 0, 5, 512 * 512);
//gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, 0);


And the problem was: when I comment the glBindFramebuffer(), the grass appears correctly with the white color (from the light point of view, which shows the matrix should be correct).
1676

But if I call glBindFramebuffer() everything just disappeared while I expect the closer grass to be brighter and further grass to be darker.

A_Shuang
03-21-2015, 06:44 AM
I was wondering to render a very simple shadow map (grass), where closer looks brighter and further looks darker, from the view of the light point, yet it did not work.

Here is my code:


//setting up buffers
gl.glGenFramebuffers(1, framebuff);
gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));

gl.glGenTextures(2, textureBuff);
gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(0));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_R32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR_MIPMAP_LINEAR);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_COLOR_ATTACHMENT0, textureBuff.get(0), 0);

gl.glBindTexture(GL4.GL_TEXTURE_2D, textureBuff.get(1));
gl.glTexStorage2D(GL4.GL_TEXTURE_2D, 1, GL4.GL_DEPTH_COMPONENT32F, displayWidth, displayHeight);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MAG_FILTER, GL4.GL_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_MIN_FILTER, GL4.GL_LINEAR_MIPMAP_LINEAR);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_MODE, GL4.GL_COMPARE_REF_TO_TEXTURE);
gl.glTexParameteri(GL4.GL_TEXTURE_2D, GL4.GL_TEXTURE_COMPARE_FUNC, GL4.GL_LEQUAL);
gl.glFramebufferTexture(GL4.GL_FRAMEBUFFER, GL4.GL_DEPTH_ATTACHMENT, textureBuff.get(1), 0);
gl.glDrawBuffer(GL4.GL_NONE);

if(gl.glCheckFramebufferStatus(GL4.GL_FRAMEBUFFER) != GL4.GL_FRAMEBUFFER_COMPLETE)
System.out.println(gl.glCheckFramebufferStatus(GL4 .GL_FRAMEBUFFER));


drawing command (not sure if it's correct):


//gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));
gl.glViewport(0, 0, displayWidth, displayWidth);
gl.glEnable(GL4.GL_POLYGON_OFFSET_FILL);
gl.glPolygonOffset(2.0f, 4.0f);

/*
gl.glClearBufferfv(GL4.GL_COLOR, 0, new float[] {0, 0, 0}, 0);
gl.glClearDepth(1.0f);
gl.glClear(GL4.GL_DEPTH_BUFFER_BIT);*/

setupMVPMatrix();
gl.glBindVertexArray(vaoBuff.get(0));

gl.glUseProgram(shaderProgram);
gl.glDrawArraysInstanced(GL4.GL_TRIANGLE_STRIP, 0, 5, 512 * 512);

gl.glDisable(GL4.GL_POLYGON_OFFSET_FILL);
//gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, 0);


when I comment the glBindFramebuffer(), the grass appears correctly with the white color (from the light point of view, which shows the matrix should be correct).
1677

But if I call glBindFramebuffer() with depth test enabled, everything just disappeared while I expect the closer grass to be brighter and further grass to be darker. I have also checked the framebuffer status, yet it seems there is no error. Any help?

Dark Photon
03-21-2015, 09:58 AM
...when I comment the glBindFramebuffer(), the grass appears correctly with the white color (from the light point of view, which shows the matrix should be correct).
1677

But if I call glBindFramebuffer() with depth test enabled, everything just disappeared...

It disappears because you're redirecting all rendering away from the system framebuffer to the FBO. Then you (apparently) don't do anything to use the results of that off-screen FBO. Result: nothing rendered in the system framebuffer.

Rendering the depth map is only the first piece of rendering with dynamically-generated shadow maps.

Dark Photon
03-21-2015, 10:11 AM
Please don't cross-post. I've combined your threads here.

A_Shuang
03-21-2015, 09:07 PM
It disappears because you're redirecting all rendering away from the system framebuffer to the FBO. Then you (apparently) don't do anything to use the results of that off-screen FBO. Result: nothing rendered in the system framebuffer.

Rendering the depth map is only the first piece of rendering with dynamically-generated shadow maps.

Could you please tell me how to use that results of that off-screen FBO, I checked both blue book and red book, and the code was ported from there.

A_Shuang
03-21-2015, 09:13 PM
It disappears because you're redirecting all rendering away from the system framebuffer to the FBO. Then you (apparently) don't do anything to use the results of that off-screen FBO. Result: nothing rendered in the system framebuffer.

Rendering the depth map is only the first piece of rendering with dynamically-generated shadow maps.

The way I did it is just like this: http://stackoverflow.com/questions/12546368/render-the-depth-buffer-into-a-texture-using-a-frame-buffer
though we have different problems.

A_Shuang
03-22-2015, 06:58 AM
Fixed finally, I didn't understand the meaning of off-screen rendering at the beginning. Just render the depth value stored in the texture into the default framebuffer for display, and everything work just fine. I can't believe I spent 5 days on this.
1684

gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, framebuff.get(0));
draw scene...(storing the depth value into the depth texture)

gl.glBindFramebuffer(GL4.GL_FRAMEBUFFER, 0);
draw scene...(comparing with the depth texture stored)