I’ve tried to follow many tutorials, but Shadow Mapping is very hard for me.
Here’s what I want to do. I have a simple cube and a plane.
[ATTACH=CONFIG]1201[/ATTACH]
Now obviously I want the cube and any object that I add to cast a shadow on the plane, using Shadow Mapping.
My current attempt just breaks the scene:
[ATTACH=CONFIG]1202[/ATTACH]
No shadow. Looks like the camera is just somewhere in the cube.
The problem can only be in the shaders or in the way I’m doing the double-render loop.
Here’s the full relevant code.
//Declaring matrices and IDs
mat4 projectionMatrix,viewMatrix,viewMatrixLight,modelMatrix,shaderMatrix;
GLuint frameBufferID = 0;
GLuint vertexBufferID[2],vertexArrayID[2],colorBufferID[2];
GLuint shader_matrix,shader_matrix2,depthBiasID;
GLuint depthTexture;
GLuint shadowMapID;
mat4 depthBiasMVP;
mat4 biasMatrix(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
//Declaring vertices position and colors
float triangles = {
(…)
}
float lines = {
(…)
}
float colors1 = {
(…)
}
float colors2 = {
(…)
}
//My shaders
GLuint shaderProgram1, shaderProgram2;
//Shaders for the depth render (1)
const char* vertexShader_Render1 =
“#version 330 core”
“layout(location = 0) in vec3 vertexPosition_modelspace;”
“uniform mat4 depthMVP;”
“void main(){”
“gl_Position = depthMVP * vec4(vertexPosition_modelspace,1);”
“}”;
const char* fragmentShader_Render1 =
“#version 330 core”
“layout(location = 0) out float fragmentdepth;”
“void main(){”
“fragmentdepth = gl_FragCoord.z;”
“}”;
//Shaders for the classic render (2)
const char* vertexShader_Render2 =
“#version 400
"
“layout(location = 0) in vec3 vp;”
“layout(location = 1) in vec3 vertexColor;”
“out vec3 fragmentColor;”
“uniform mat4 shader_matrix;”
“uniform mat4 depthBiasMVP;”
“void main () {”
" gl_Position = shader_matrix * vec4 (vp, 1.0);”
" fragmentColor = vertexColor;"
" ShadowCoord = DepthBiasMVP * vec4(vp,1);"
“}”;
const char* fragmentShader_Render2 =
“#version 330 core”
“in vec3 fragmentColor;”
“in vec4 ShadowCoord;”
“layout(location = 0) out vec3 color;”
“uniform sampler2DShadow shadowMap;”
“void main(){”
“vec3 LightColor = vec3(1,1,1);”
“vec3 MaterialDiffuseColor = texture2D( myTextureSampler, UV ).rgb;”
“float visibility = 1.0;”
“if ( texture2D( shadowMap, ShadowCoord.xy ).z < ShadowCoord.z-0.005){”
" visibility = 0.5;"
“}”
“color = visibility * fragmentColor * LightColor;”
“}”;
void initialise() {
(…)
//Making buffers to store vertices and colors for both triangles and lines
glGenBuffers (1, &vertexBufferID[0]);
glBindBuffer (GL_ARRAY_BUFFER, vertexBufferID[0]);
glBufferData (GL_ARRAY_BUFFER, sizeof(triangles) * sizeof (float), triangles, GL_STATIC_DRAW);
glGenBuffers (1, &vertexBufferID[1]);
glBindBuffer (GL_ARRAY_BUFFER, vertexBufferID[1]);
glBufferData (GL_ARRAY_BUFFER, sizeof(lines) * sizeof (float), lines, GL_STATIC_DRAW);
glGenBuffers (1, &colorBufferID[0]);
glBindBuffer (GL_ARRAY_BUFFER, colorBufferID[0]);
glBufferData (GL_ARRAY_BUFFER, sizeof(colors1) * sizeof (float), colors1, GL_STATIC_DRAW);
glGenBuffers (1, &colorBufferID[1]);
glBindBuffer (GL_ARRAY_BUFFER, colorBufferID[1]);
glBufferData (GL_ARRAY_BUFFER, sizeof(colors2) * sizeof (float), colors2, GL_STATIC_DRAW);glGenVertexArrays (1, &vertexArrayID[0]);
glBindVertexArray (vertexArrayID[0]);
glEnableVertexAttribArray (0);
glBindBuffer (GL_ARRAY_BUFFER, vertexBufferID[0]);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (1);
glBindBuffer (GL_ARRAY_BUFFER, colorBufferID[0]);
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glGenVertexArrays (1, &vertexArrayID[1]);
glBindVertexArray (vertexArrayID[1]);
glEnableVertexAttribArray (0);
glBindBuffer (GL_ARRAY_BUFFER, vertexBufferID[1]);
glVertexAttribPointer (0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableVertexAttribArray (1);
glBindBuffer (GL_ARRAY_BUFFER, colorBufferID[1]);
glVertexAttribPointer (1, 3, GL_FLOAT, GL_FALSE, 0, NULL);
//Compiling and linking shaders
//(shaderProgram1 is for first render, shaderProgram2 is for second render)
GLuint vs[2],fs[2];
vs[0] = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vs[0], 1, &vertexShader_Render1, NULL);
glCompileShader (vs[0]);
fs[0] = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fs[0], 1, &fragmentShader_Render1, NULL);
glCompileShader (fs[0]);
shaderProgram1 = glCreateProgram ();
glAttachShader (shaderProgram1, fs[0]);
glAttachShader (shaderProgram1, vs[0]);
glLinkProgram (shaderProgram1);
vs[1] = glCreateShader (GL_VERTEX_SHADER);
glShaderSource (vs[1], 1, &vertexShader_Render1, NULL);
glCompileShader (vs[1]);
fs[1] = glCreateShader (GL_FRAGMENT_SHADER);
glShaderSource (fs[1], 1, &fragmentShader_Render2, NULL);
glCompileShader (fs[1]);
shaderProgram2 = glCreateProgram ();
glAttachShader (shaderProgram2, fs[1]);
glAttachShader (shaderProgram2, vs[1]);
glLinkProgram (shaderProgram2);
//Getting uniforms inside shaders
shader_matrix = glGetUniformLocation(shaderProgram1, “shader_matrix”);
shadowMapID = glGetUniformLocation(shaderProgram1, “shadowMap”);
depthBiasID = glGetUniformLocation(shaderProgram2, “depthBiasMVP”);
shader_matrix2 = glGetUniformLocation(shaderProgram2, “depthMVP”);
//Setting up matrices that won’t change
projectionMatrix = perspective(radians(45.0f), d.w/d.h, 0.1f, 100.0f);
viewMatrix = lookAt(vec3(10,15,10), vec3(0,0,0), vec3(0,1,0));
viewMatrixLight = lookAt(vec3(-10,15,-10), vec3(0,0,0), vec3(0,1,0)); //I try to put the light at the opposite of the camera//Setting up the frame buffer
glGenFramebuffers(1, &frameBufferID);
glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);
glDrawBuffer(GL_NONE);
}
void loop() {
modelMatrix = mat4();glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_ALPHA_TEST);
//Setting up some stuff glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID); glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0); glEnable(GL_DEPTH_TEST); glViewport(0,0,1024,1024);
glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
//Enabling program 1 glUseProgram(shaderProgram1);
//Setting up matrix from the point of view of the light, and sending as uniform. shaderMatrix = projectionMatrix * viewMatrixLight * modelMatrix; glUniformMatrix4fv(shader_matrix2, 1, GL_FALSE, &shaderMatrix[0][0]);
//DRAWING glBindVertexArray (vertexArrayID[0]); glDrawArrays (GL_TRIANGLES, 0, 42);
glBindVertexArray (vertexArrayID[1]); glDrawArrays (GL_LINES, 0, 32);
//Setting up some stuff glBindFramebuffer(GL_FRAMEBUFFER, 0); glViewport(0,0,1024,768);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_ALPHA_TEST);
//Enabling program 2 glUseProgram(shaderProgram2);
//Setting up matrices and sending as uniform shaderMatrix = projectionMatrix * viewMatrix * modelMatrix; //from the point of view of the camera glUniformMatrix4fv(shader_matrix, 1, GL_FALSE, &shaderMatrix[0][0]);
depthBiasMVP = biasMatrix*shaderMatrix; glUniformMatrix4fv(depthBiasID, 1, GL_FALSE, &depthBiasMVP[0][0]);
//Sending shadow map glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, depthTexture); glUniform1i(shadowMapID, 1);
//DRAWING glBindVertexArray (vertexArrayID[0]); glDrawArrays (GL_TRIANGLES, 0, 42);
glBindVertexArray (vertexArrayID[1]); glDrawArrays (GL_LINES, 0, 32);
SwapBuffers();
}
If you’re good at this, please take a look and tell me what’s missing or completely wrong.