Can't do simple Shadow Mapping

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.

First, please use [ code ] … [ /code ] tags when posting code.

One thing that I notice is that you’re using vertexShader_Render1 for both programs. vertexShader_Render2 isn’t used anywhere.

Another thing is that only vertexShader_Render2 has a newline after the #version directive. The other three shaders don’t, e.g.

The above is identical to:


const char* vertexShader_Render1 =
    "#version 330 corelayout(location = 0) in vec3 vertexPosition_modelspace;"

Any preprocessor directive must be terminated with a newline.

This should cause the shaders to fail to compile; And the second program with (vertexShader_Render1 and fragmentShader_Render2) should fail to link, as fragmentShader_Render2 references inputs named fragmentColor and ShadowCoord but vertexShader_Render1 doesn’t have those as outputs).

Always check the results of compilation and linking, and display the log if there’s an error.

The other thing is that your second picture has the camera in a completely different location. That may be a consequence of shader-related bugs. Otherwise, it indicates that you’re passing the wrong matrix to the shader program used for normal rendering. Nothing that the depth rendering step does should affect the view for the normal rendering step.

Thank you for paying attention to the code. I actually found some of those bugs yesterday and wanted to update this post but I had a problem with my connexion.

Indeed, the lack of "
" was preventing the shaders from working. I’m an idiot.
Also, as you said I did some mistakes like linking the wrong shaders, and allocating the uniforms in the wrong program.

Now, there are still some problems. Here’s the output:

[ATTACH=CONFIG]1203[/ATTACH]

The initial scene is back, everything is getting drawn, no idea if shadows are working, but it’s all red. I’ve checked, the color isn’t passing through the shaders.
And I’ve spent a few hours but I can’t figure out the problem.

Here are the shaders involved:


const char* vertexShader_Render2 =
"#version 400
"
"layout(location = 0) in vec3 vp;"
"layout(location = 1) in vec3 vertexColor;"
"out vec3 fragmentColor;"
"out vec4 ShadowCoord;" 
"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
"
"layout(location = 0) out vec3 color;"
"in vec3 fragmentColor;"
"in vec4 ShadowCoord;"
"uniform sampler2DShadow shadowMap;"
"void main(){"
	"color = fragmentColor;"
"}"; 


The first shader works. If I remove it everything disappears.
The second shader, that I put color = vec3(1.0,1.0,1.0); or that I remove the entire shader, it changes nothing. Scene is red with or without shader. I don’t know how to check if compilation went well.

I’m linking them correctly to ID shaderProgram2 :


        vs[1] = glCreateShader (GL_VERTEX_SHADER);
	glShaderSource (vs[1], 1, &vertexShader_Render2, 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);

And here’s my drawing loop:


                modelMatrix = mat4(1.0f); 
	
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glDisable(GL_ALPHA_TEST);

		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); 
		glUseProgram(shaderProgram1);

		shaderMatrix = projectionMatrix * viewMatrixLight * modelMatrix; 
		glUniformMatrix4fv(shader_matrix2, 1, GL_FALSE, &shaderMatrix[0][0]);

		glBindVertexArray (vertexArrayID[0]);
		glDrawArrays(GL_TRIANGLES, 0, 42);

		glBindVertexArray (vertexArrayID[1]);
		glDrawArrays(GL_LINES, 0, 32);

		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		glViewport(0,0,1920,1024);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
		glEnable(GL_ALPHA_TEST);

		//Using the program in question (works since position is getting processed correctly)
		glUseProgram(shaderProgram2);
		
		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]);

		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, depthTexture);
		glUniform1i(shadowMapID, 1);

		glBindVertexArray (vertexArrayID[0]);
		glDrawArrays (GL_TRIANGLES, 0, 42);

		glBindVertexArray (vertexArrayID[1]);
		glDrawArrays (GL_LINES, 0, 32);

		SDL_GL_SwapBuffers();

How can I fix color? And then we can see if any shadow is working or not.

EDIT: Added “out vec4 ShadowCoord;” on the vertex shader since you said it won’t link if the in don’t correspond to outs.
Still same result.

After calling glCompileShader(), call glGetShaderiv(shader, GL_COMPILE_STATUS). If it returns zero, there was an error, so call glGetShaderInfoLog() to retrieve the log messages.

After calling glLinkProgram(), call glGetProgramiv(program, GL_LINK_STATUS). If it returns zero, there was an error, so call glGetProgramInfoLog() to retrieve the log messages.

Also, at the end of each major function (initialisation, render), call glGetError(). Any non-zero return value indicates an error.

But when I try to retrieve the value with glGetShaderiv(vs[0], GL_COMPILE_STATUS) into a variable it always says it’s the wrong type. How am I supposed to assign it?

And some new info. I don’t know why, but affecting the other shaders (the ones used in the first render) also does effects on what appears on the screen (which is definitly what I draw the second time, using shaderProgram2).

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

Let’s say I turn the fragment into:


const char* fragmentShader_Render1 =
"#version 330 core
"
"layout(location = 0) out float fragmentdepth;"
"void main(){"
"fragmentdepth = 0;"
"}"; 

As a result, drawn triangles when I’m no longer using that shader program are black
[ATTACH=CONFIG]1204[/ATTACH]

Let’s say I change the vertex shader like this:


const char* vertexShader_Render1 =
"#version 330 core
"
"layout(location = 0) in vec3 vertexPosition_modelspace;"
"uniform mat4 depthMVP;"
"void main(){"
"gl_Position =  depthMVP * vec4(0,0,0,1);"
"}";

Okay now nothing appears, camera probably in wrong position

[ATTACH=CONFIG]1205[/ATTACH]

No idea why it has effects when I’m using the other program… During those tests I removed the draw part in the first render.

I feel like I should just throw these shaders but I wouldn’t know how to write new ones…

EDIT: Okay so by using glUseProgram(0) I found out that it was actually still using the other program. The second render program simply isn’t working, it was the first one doing the work.

 
glUseProgram(0);
//Enabling program 2 
glUseProgram(shaderProgram2);

That’s way more problems that I expected…

Like most glGetWhatever() functions, the result is stored in a location to which a pointer is passed in (this allows for queries which return more than a single integer, without needing to add another function).


GLint result;
glGetShaderiv(vs[0], GL_COMPILE_STATUS, &result);
if (!result) {
    char log[64*1024];
    glGetShaderInfoLog(vs[0], sizeof log, (GLsizei *) NULL, log);
    fputs(log, stderr);
}

Passing an invalid program (e.g. one which failed to link) to glUseProgram() should result in an error (as reported by glGetError()). Unless glGetError() returns zero (GL_NO_ERROR), you shouldn’t expect anything from your program. At a minimum, check for errors after initialisation and after rendering the first frame. If there are any errors, add additional checks until you determine which function caused them. There’s really no point in looking at anything else until actual errors are fixed.

I think I should better give up on modern OpenGL. 3 days of trying and no shadows. No official clean source-code to make it work. This is exhausting.

Okay I gave myself a bit of patience and I did one last try. I started everything again from scratch, step by step, making the shaders correctly.

Aaaannd… IT WORKS! YEES!

[ATTACH=CONFIG]1208[/ATTACH]

Now I’m working ASAP on making it smooth.

It’s all perfect.

[ATTACH=CONFIG]1209[/ATTACH]

Here is the code for those who might be interested.


    mat4 projectionMatrix,projectionMatrixLight,viewMatrix,viewMatrixLight,modelMatrix,shaderMatrix,depthBiasMVP; 

    GLuint 
        vs[2],fs[2], 
        frameBufferID,depthTexture, 
        vertexBufferID[2],vertexArrayID[2],colorBufferID[2],
        shader_matrix,shader_matrix2,depthBiasMatrix,
        shadowMapID; 

    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


      );

        float triangles[] = {
          //Vertices for triangles
        };

        float lines[] = {
            //Vertices for lines
        };

        float colors1[] = {
            //Colors for triangles
        };

        float colors2[] = {
            //Colors for lines
        }; 

        GLuint shaderProgram1, shaderProgram2; 
    const char* vertexShader_Render1 =
    "#version 400 core
"
    "layout(location = 0) in vec3 position;"
    "layout(location = 1) in vec3 vertexColor;"
    "out vec3 fragmentColor;" 
    "out vec4 shadowCoord;"
    "uniform mat4 finalMatrix;"
    "uniform mat4 depthBiasMatrix;"
    "void main(){"
    "gl_Position = finalMatrix * vec4(position,1.0f);"
    "shadowCoord = depthBiasMatrix * vec4(position,1.0f);"
    "fragmentColor = vertexColor;"
    "}";

    const char* fragmentShader_Render1 =
    "#version 330 core
"
    "in vec3 fragmentColor;"
    "in vec4 shadowCoord;"
    "out vec3 color;" 
    "uniform sampler2D shadowMap;"
    "void main()"
    "{ "   
    "float visibility = 1.0;"
    "if (texture ( shadowMap, shadowCoord.xy ).z < shadowCoord.z-0.001) {"
    "visibility = 0.75;"
    "}"
    "color = fragmentColor * visibility;"
    "}";

    const char* vertexShader_Render2 =
    "#version 400 core
"
    "layout(location = 0) in vec3 position;"
    "uniform mat4 lightMatrix;"
    "void main(){"
    "gl_Position = lightMatrix * vec4(position,1.0f);"
    "}";

    const char* fragmentShader_Render2 =
    "#version 330 core
"
    "layout(location = 0) out float fragmentdepth;"
    "void main()"
    "{ "   
    "fragmentdepth = gl_FragCoord.z;"
    "}";


    void initialise() {

    glClearColor(0.5f,0.5f,0.5f,1.0f);  

    //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

    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_Render2, 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);

    shader_matrix = glGetUniformLocation(shaderProgram1, "finalMatrix");
    depthBiasMatrix = glGetUniformLocation(shaderProgram1, "depthBiasMatrix");
    shadowMapID = glGetUniformLocation(shaderProgram1, "shadowMap");
    shader_matrix2 = glGetUniformLocation(shaderProgram2, "lightMatrix");

    projectionMatrix = perspective(radians(45.0f), d.w/d.h, 0.1f, 100.0f);
    projectionMatrixLight = ortho(-10.0f,10.0f,-10.0f,10.0f, -5.0f, 30.0f);

    viewMatrix = lookAt(vec3(-17,25,-17), vec3(0,0,0), vec3(0,1,0));
    viewMatrixLight = lookAt(vec3(10,10,10), vec3(0,0,0), vec3(0,1,0)); 

    glUseProgram(shaderProgram1);

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

    glDrawBuffer(GL_NONE);

    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void drawScene() { 
modelMatrix = mat4(); 
rotateMatrix(radians(d.time),0,1,0); 
glBindVertexArray (vertexArrayID[0]);
glDrawArrays(GL_TRIANGLES, 0, 42);

glBindVertexArray (vertexArrayID[1]);
glDrawArrays(GL_LINES, 0, 32);
}


void renderScene() {

    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    //glCullFace(GL_FRONT);

    glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
    glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);

    glViewport(0,0,1024,1024);

    glUseProgram(shaderProgram2);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    shaderMatrix = projectionMatrixLight * viewMatrixLight * modelMatrix; 
    glUniformMatrix4fv(shader_matrix2, 1, GL_FALSE, &shaderMatrix[0][0]);

    drawScene(); 

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0,0,d.w,d.h);

    glUseProgram(shaderProgram1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 


    depthBiasMVP = biasMatrix * shaderMatrix; 
    glUniformMatrix4fv(depthBiasMatrix, 1, GL_FALSE, &depthBiasMVP[0][0]);

    shaderMatrix = projectionMatrix * viewMatrix * modelMatrix; 
    glUniformMatrix4fv(shader_matrix, 1, GL_FALSE, &shaderMatrix[0][0]);

    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, depthTexture);
    glUniform1i(shadowMapID, 1);

    drawScene(); 

    SDL_GL_SwapBuffers(); 
}

Good job! Perseverance pays off!

I’m not sure if I understood this since I’ve no experience with shadows but does the code first render from the light source’s point of view and save the depth of the render in a texture with the frame buffer changes at the beginning and then uses that result in the real render to check the fragments positions in camera view and if it should be lit based on its depth from the textures point of view.

Does shadow volume work the same too?

Yes.
.

No. Shadow volumes extrude an object’s silhouette in the direction of the light to obtain a set of polygons bounding the volume in shadow, then render that into the stencil buffer. Shadow volumes are basically an application of constructive solid geometry, calculating the intersection of the scene with the shadow volume.