Problem getting shadow mapping to work correctly

So I have spent the last few days trying and failing to get this shadow mapping working. Basically all I am getting is a rendering of a mostly white scene albeit shaded via lighting so you can see all the objects, however there is no colour, no textures and most importantly no shadows. Colour and textures was working correctly before I started to implement this shadow mapping code. I suspect the problem lies in my shader code so I’ll post them here:

First is the vertex shader:


#version 450 core

uniform mat4	mv_Matrix;			// ModelView Matrix
uniform mat4	mvp_Matrix;			// ModelViewProjection Matrix
uniform mat3	normal_Matrix;		// Normal Matrix
uniform mat4	shadow_Matrix;		// *** NEW **** Shadow Matrix

in vec4			in_position;
in vec3			in_colour;
in vec3			in_normal;
in vec2			in_texcoord;

out vec4		out_position;
out vec3		out_colour;
out vec3		out_normal;
out vec2		out_texcoord;
out vec4		out_shadowcoord;


void main()
{
	// Convert normal and vertex into eye-space coordinates
	out_normal = normalize(normal_Matrix * in_normal);
	out_position = mv_Matrix * in_position;

	// Send the texture coordinates to the fragment shader
	out_texcoord = in_texcoord;
	
	// Send the input colour to the fragment shader
	out_colour = in_colour;

	// **** NEW **** Shadow Matrix converts from modelling coordinates to shadow map coordinates
	out_shadowcoord = shadow_Matrix * in_position;

	// Convert position to clip coordinates and pass to fragment shader
	gl_Position = mvp_Matrix * in_position;
}

Fragment shader:


#version 450 core

struct LightInfo {
	vec3	ambient;
	vec3	diffuse;
	vec3	specular;
	vec4	position;
	vec4	halfVector;
};

struct MaterialInfo {
	vec3	Ka;					// Ambient reflectivity
	vec3	Kd;					// Diffuse reflectivity
	vec3	Ks;					// Specular reflectivity
	float	Shininess;			// Specular shininess factor
};

struct FogInfo {
	vec3	fog_colour;			// Fog colour
	float	min_dist;			// Minimum distance to fog start
	float	max_dist;			// Maximum distance to fog end
};

uniform LightInfo Light;			// Light properties
uniform MaterialInfo Material;		// Material properties
uniform FogInfo Fog;				// Fog properties

subroutine vec4 renderModelType();
subroutine uniform renderModelType RenderType;

subroutine void RenderPassType();
subroutine uniform RenderPassType RenderPass;

uniform sampler2D	s_texture;
uniform sampler2DShadow Shadow_Map;

in vec4			out_position;
in vec3			out_colour;
in vec3			out_normal;
in vec2			out_texcoord;
in vec4			out_shadowcoord;

out vec4		frag_colour;


vec4 phongModel()
{
	vec3 S;
	if(Light.position.w == 0.0) {
		S = normalize(vec3(Light.position));				// Directional light source
	}
	else {
		S = normalize(vec3(Light.position - out_position));		// Positional light source
	}

	vec3 V = normalize(-out_position.xyz);
	vec3 R = reflect(-S, out_normal);
	//vec3 ambient = vec3(0.0, 1.0, 0.0) * Material.Ka;
	vec3 ambient = Light.ambient * Material.Ka;
	float sDotN = max(dot(S, out_normal), 0.0);
	vec3 diffuse = Light.diffuse * Material.Kd * sDotN;
	vec3 specular = vec3(0.0);
	
	if(sDotN > 0.0) {
		specular = Light.specular * Material.Ks * pow(max(dot(R,V), 0.0), Material.Shininess);
	}

	return vec4(ambient + diffuse + specular, 1.0);
}

vec4 GetLightColour()
{
	if(gl_FrontFacing){	return phongModel(); }
	else return vec4(0.0, 0.0, 0.0, 1.0);
}

subroutine(renderModelType)
vec4 ReturnObjectColour()
{
	vec4 light_colour = GetLightColour();
	return vec4(light_colour.rgb, 1.0);
}

subroutine(renderModelType)
vec4 ReturnTextureColour()
{
	vec4 texture_colour = texture2D(s_texture, out_texcoord);
	vec4 light_colour = GetLightColour();
//	return vec4(out_colour * texture_colour.rgb, texture_colour.a);							// Lighting disabled
	return vec4(light_colour.rgb * out_colour * texture_colour.rgb, texture_colour.a);		// Lighting enabled
}

subroutine(RenderPassType)
void shadeWithShadow()
{
	vec4 ambient = vec4(Light.ambient,1.0);			// compute ambient component
	vec4 pixel_colour = RenderType();

	// Do the shadow-map look-up
	float shadow = textureProj(Shadow_Map, out_shadowcoord);

	// If the fragment is in shadow, use ambient light only
	frag_colour = vec4(pixel_colour * shadow + ambient);
}

subroutine(RenderPassType)
void recordDepth()
{
	// Do nothing, depth will be written automatically
}

void main()
{
	RenderPass();
//	vec4 final_colour = RenderType();	
//	frag_colour = final_colour;
}

Here is my main rendering code:


void RenderScene()
{
	glClear(GL_DEPTH_BUFFER_BIT);
	// FIRST RENDERING PASS...
	light_frustum.UpdateCamera(&M_Viewing);
	glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
	glViewport(0, 0, 512, 512);
	UpdateProjection(60.0f, 512.0f, 512.0f, 1.0f, 1000.0f);
	glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &pass1Index);		// Select the subroutine to use in the shader
	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);
	Draw3D();                                         // Draws the various objects in the scene inc. DrawHouse()
	
	// SECOND RENDERING PASS...
	camera.UpdateCamera(&M_Viewing);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport(0, 0, 1920, 1080);
	UpdateProjection(45.0f, 1920.0f, 1080.0f, 0.5f, 1000.0f);
	glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &pass2Index);		// Selected the second subroutine in the shader
	glDisable(GL_CULL_FACE);
	UpdateLightPosition();
	Draw3D();
}

Creation of the framebuffer object should be OK…


void SetupFBO(void)
{
	GLsizei shadowMapWidth = 512;
	GLsizei shadowMapHeight = 512;

	glGenTextures(1, &depthTexture);
	glBindTexture(GL_TEXTURE_2D, depthTexture);

	glTexStorage2D(GL_TEXTURE_2D, 1, GL_DEPTH_COMPONENT24, shadowMapWidth, shadowMapHeight);

	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_BORDER);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
	glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS);

	// Assign the shadow map to texture unit 0
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, depthTexture);

	// Create and setup the FBO
	glGenFramebuffers(1, &shadowFBO);
	glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
	GLenum drawBuffers[] = { GL_NONE };
	glDrawBuffers(1, drawBuffers);

	GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if (result == GL_FRAMEBUFFER_COMPLETE) {
		printf("Framebuffer is complete.
");
	}
	else {
		printf("Framebuffer is not complete.
");
	}

	// Revert to the default framebuffer for now
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

What else? My object rendering code looks like this:


void DrawHouse(void)
{
	if (textures_enabled) {	glUseProgram(phong_program); }
	else { glUseProgram(flatshade_program); }

	house.Translate(vec3(-6.0f, -5.0f, 15.0f));			// Position the house object in world space

	glUniformSubroutinesuiv(GL_FRAGMENT_SHADER, 1, &textureIndex);
	
	if (textures_enabled) { house.TransformTest(M_Viewing, M_Projection, light_eye_space, ambient_light, diffuse_light, specular_light); }
	else { house.TransformRT(M_Viewing, M_Projection); }
	
	house.ActivateTexture(GL_TEXTURE0, 0);				// Activate texture 0
	house.Draw();
}

Transform test where number crunching happens…


void Mesh3D::TransformTest(mat4 viewMatrix, mat4 projectionMatrix, vec4 light_position, vec4 light_ambient, vec4 diffuse_light, vec4 specular_light)
{
	mModelMatrix = mTranslationMatrix * mRotationMatrix;
	mModelViewMatrix = viewMatrix * mModelMatrix;
	mModelViewMatrix.GetMatrix(mv_Matrix);
	mModelViewMatrix.GetNormalMatrix(normal_Matrix);
	
	// Now we calculate the modelview-projection matrix
	mMVPMatrix = projectionMatrix * mModelViewMatrix;
	mMVPMatrix.GetMatrix(mvp_Matrix);

	// Calculate the normal matrix by taking the inverse-transpose of the modelview matrix
//	mNormalMatrix = mModelViewMatrix;
//	mNormalMatrix.InvertM();
//	mNormalMatrix.TransposeM();
//	mNormalMatrix.GetNormalMatrix(normal_Matrix);

	// TEST
	mLightPV = mShadowBias * projectionMatrix * viewMatrix;
	mShadowMatrix = mLightPV * mModelMatrix;
	mShadowMatrix.GetMatrix(shadow_Matrix);

	glUniform3f(uLightAmbientLocation, light_ambient.x, light_ambient.y, light_ambient.z);
	glUniform3f(uLightDiffuseLocation, diffuse_light.x, diffuse_light.y, diffuse_light.z);
	glUniform3f(uLightSpecularLocation, specular_light.x, specular_light.y, specular_light.z);
	glUniform4f(uLightPositionLocation, light_position.x, light_position.y, light_position.z, light_position.w);
	glUniform3f(uMatAmbientLocation, mat.ambient.x, mat.ambient.y, mat.ambient.z);
	glUniform3f(uMatDiffuseLocation, mat.diffuse.x, mat.diffuse.y, mat.diffuse.z);
	glUniform3f(uMatSpecularLocation, mat.specular.x, mat.specular.y, mat.specular.z);
	glUniform1f(uMatShininessLocation, mat.shininess);
	glUniformMatrix4fv(uMVMatrixLocation, 1, GL_FALSE, mv_Matrix);
	glUniformMatrix4fv(uMVPMatrixLocation, 1, GL_FALSE, mvp_Matrix);
	glUniformMatrix3fv(uNormalMatrixLocation, 1, GL_FALSE, normal_Matrix);
	glUniformMatrix4fv(uShadowMatrixLocation, 1, GL_FALSE, shadow_Matrix);
	glUniform1i(uTexture0Location, 0);
	glUniform1i(uShadowMapLocation, 0);
}

My shader loading code looks like this:


	if (!s.LoadShader("Shaders/phong.vert", "Shaders/phong.frag")) { return FALSE; }
	else
	{
		phong_program = s.CreateProgram();
		if (phong_program == 0) { return FALSE; }

		glBindAttribLocation(phong_program, 0, "in_position");
		glBindAttribLocation(phong_program, 1, "in_colour");
		glBindAttribLocation(phong_program, 2, "in_normal");
		glBindAttribLocation(phong_program, 3, "in_texcoord");
		glBindFragDataLocation(phong_program, 0, "frag_colour");

		if (!s.LinkProgram(phong_program)) { return FALSE; }
	}

All uniforms etc are correctly initialised. I have tested the light transformations and the view is correctly being rendered from the lights position and correct direction in the first pass. I just have no idea why the textures aren’t appearing and no shadows either. I must be doing something wrong.

I’ve tried to post a screenshot of what the scene looks like but the ‘Manage Attachments’ doesn’t allow you to attach anything. Bizarre.

EDIT: OK I just changed this line in TransformTest from 3fv to 4fv:
glUniformMatrix4fv(uShadowMatrixLocation, 1, GL_FALSE, shadow_Matrix);

I realised from posting here that I had made a mistake there. Now I see some texturing swimming across the objects. Looks super strange. Wish I could make a short video of this effect. Still no shadow effect though. This just gets wierder…

OK, I’ve managed to record a short clip using nVidia GeForce Experience recording facility. It seemed to work OK so I’m now uploading to YouTube.

Here is the direct link:

https://youtu.be/GEZZALOfYuQ

Really hope someone can help as I’m totally stumped. :frowning:

The fragment shader has two subroutine uniforms (RenderType and RenderPass) but each call to glUniformSubroutinesuiv() has a count of one. That should result in the call failing with GL_INVALID_VALUE.

Are you checking for errors?

[QUOTE=GClements;1286333]The fragment shader has two subroutine uniforms (RenderType and RenderPass) but each call to glUniformSubroutinesuiv() has a count of one. That should result in the call failing with GL_INVALID_VALUE.

Are you checking for errors?[/QUOTE]

You’re right I forgot to enable error checking. I have it turned off by default. I get this error:

API:Undefined Behavior [Medium Warning] (131222) : Program undefined behavior warning: Sampler object 0 is bound to non-depth texture 1, yet it is used with a program that uses a shadow sampler. This is undefined behavior.

I’m not too clear on how glUniformSubroutinesuiv actually works? So should my calls to this be a count of 2? I tried that and most of the geometry just disappeared.

[QUOTE=reaktor24;1286336]I get this error:

API:Undefined Behavior [Medium Warning] (131222) : Program undefined behavior warning: Sampler object 0 is bound to non-depth texture 1, yet it is used with a program that uses a shadow sampler. This is undefined behavior.
[/QUOTE]
That’s a warning; it’s unrelated to the issue with subroutine uniforms, but probably relevant to shadow mapping.

It’s related to this:

You’re setting both sampler uniforms to refer to texture unit 0. It’s an error to execute a program where sampler uniforms of different types refer to the same texture unit. If you use more than one texture, you have to bind them to different texture units (even if they’re bound to different targets).

Actual GL errors are queried by calling glGetError(). This isn’t particularly convenient as a means to identify the source of errors; it’s useful mostly to confirm that no errors have occurred (which should be the case; a correct program shouldn’t generate any errors).

The count parameter should be equal to the number of active subroutine uniforms, which can be queried with glGetProgramStageiv() with pname equal to GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS.

glUniformSubroutinesuiv() sets the values of all subroutine uniforms at once; each element in the array sets the value for one subroutine uniform.

glGetSubroutineIndex() returns the index of a subroutine given its name. glGetSubroutineUniformLocation() returns the location of a subroutine uniform given its name. But you can use the [var]location[/var] layout qualifier on the subroutine uniforms and the [var]index[/var] layout qualifier on subroutine functions to avoid the need to query these values in the client code.

Alternatively, you could just avoid the use of subroutines altogether, and just use different programs for generating the depth map and for rendering.

Yes it looks like you’re right. I changed them all (count values) to 2 and I am getting this error message in my debug log file:

API:OpenGL Error [MAJOR PROBLEM] (1282) : GL_INVALID_OPERATION error generated. Wrong component type or count.

I just need to track down which function is calling the error. Maybe I will put them in different shader files as this is starting to be a pain.

From the warnings and errors you’re reporting, it looks like you’re using NVidia drivers. In that case, you can just enable a debug context, register a debug message callback function, and then put a breakpoint on that callback function. It’ll get called whenever the any GL error or warning is triggered, with the entire callstack of functions down to the GL call that triggered it on the stack.

This makes tracking down the cause of GL errors really easy.

Alternatively, inside your GL debug message callback, you can just put some code that dumps not only the warning/error but also the call stack.

NOTE: You can access this functionality through ARB_debug_output, which has been supported by NVidia drivers for many years. It’s also part of core OpenGL 4.3+.

[QUOTE=Dark Photon;1286351]From the warnings and errors you’re reporting, it looks like you’re using NVidia drivers. In that case, you can just enable a debug context, register a debug message callback function, and then put a breakpoint on that callback function. It’ll get called whenever the any GL error or warning is triggered, with the entire callstack of functions down to the GL call that triggered it on the stack.

This makes tracking down the cause of GL errors really easy.

Alternatively, inside your GL debug message callback, you can just put some code that dumps not only the warning/error but also the call stack.

NOTE: You can access this functionality through ARB_debug_output, which has been supported by NVidia drivers for many years. It’s also part of core OpenGL 4.3+.[/QUOTE]

Hi Dark Photon. Thanks for the response. I am using NVidia Geforce GTX980 so you are correct. Plus I am also using a debug callback function which creates a log file. How do you detect the function that caused the error though? I’ve tried skipping through the code but it just ends up giving me a ‘nvoglv64.pdb no loaded’ error message. I’ve tried to get this working by downloading files from the Microsoft symbol servers but it didn’t work.

EDIT:

I’ve just fixed a small error with my debug callback function. I hadn’t included an append option so it was only writing one error at a time.

The errors are mainly ‘Invalid shader subroutine uniform’ and ‘wrong component type or count’ errors. There is one that stands out but it says its only a warning:

API:Undefined Behavior [Medium Warning] (131222) : Program undefined behavior warning: Sampler object 0 has depth compare enabled. It is being used with depth texture 6, by a program that samples it with a regular sampler. This is undefined beahvior.

  1. Put a breakpoint on your debug callback
  2. Run your program
  3. When the breakpoint triggers, look at the call stack.

That at least used to work last time I tried it.

The errors are mainly ‘Invalid shader subroutine uniform’ and ‘wrong component type or count’ errors. There is one that stands out but it says its only a warning:

API:Undefined Behavior [Medium Warning] (131222) : Program undefined behavior warning: Sampler object 0 has depth compare enabled. It is being used with depth texture 6, by a program that samples it with a regular sampler. This is undefined beahvior.

I’d fix this. I recall talking to someone that tracked down a nasty crash or screen corruption problem on NVidia drivers that was being triggered by mismatching either depth compare state or texture type with a shader that was expecting a depth texture with depth compare set (or vice versa). It was caused by an app bug, but the resulting problem wasn’t easy to track back to the instigating code.

I have never used the call stack before so I’m a bit of a beginner in that respect.

It doesn’t appear to be telling me much. Once inside the debug callback function all I see in the callstack is this:

> ShaderProject.exe!debugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char * message, void * param) Line 1261 C++

Maybe I have it setup wrong? I’m not sure. I’m using Visual Studio 2015 Community Edition.

[QUOTE=reaktor24;1286386]I have never used the call stack before so I’m a bit of a beginner in that respect.

It doesn’t appear to be telling me much. Once inside the debug callback function all I see in the callstack is this:

> ShaderProject.exe!debugCallback(…) Line 1261 C++

Maybe I have it setup wrong? I’m not sure. I’m using Visual Studio 2015 Community Edition.[/QUOTE]

Run your program. Bring up the callstack window (https://msdn.microsoft.com/en-us/library/a3694ts5.aspx). Omitting the line numbers and the “C++” mentions, you should see something like this:


ShaderProject.exe!debugCallback(...)
nvoglv64.dll!0000000069450b3b()     
[Frames below may be incorrect and/or missing, no symbols loaded for nvoglv64.dll]    
nvoglv64.dll!000000006921c53f()     
nvoglv64.dll!000000006921c62c()     
nvoglv64.dll!000000006921c5d5()     
nvoglv64.dll!000000006957d298()     
nvoglv64.dll!000000006957f859()     
nvoglv64.dll!000000006957c69b()     
nvoglv64.dll!00000000691ee012()     
nvoglv64.dll!00000000691f9053()   
ShaderProject.exe!func6(...)
ShaderProject.exe!func5(...)
ShaderProject.exe!func4(...)
ShaderProject.exe!func3(...)
ShaderProject.exe!func2(...)
ShaderProject.exe!func1(...)
ShaderProject.exe!func0(...)
...
ShaderProject.exe!main(int argc, char * * argv) 
ShaderProject.exe!__tmainCRTStartup() 
ShaderProject.exe!mainCRTStartup() 
kernel32.dll!00000000772959cd()     
ntdll.dll!00000000774ca561()     

This is where you are currently in your code. Skip past all the frames that are in the NVidia GL library (“nvoglv64.dll…”) as there’s not much you can do with those. Double-click on the first stack frame that is inside of your code (i.e. ShaderProject.exe) – In the example above, I’ve named it func6(). This is the bottom-most frame in your code and should put you right on a line where you’ve made a GL call. This GL call is likely the one that triggered the error, warning, or info message that the callback was called for.

Thanks for that clear explanation. Seems simple enough.

Unfortunately I don’t get any ShaderProject.exe stack frames. All I can see is a list of 12 DLL frames.

I’ve just tried it from a couple of other points in my code and it does work correctly as you explained. It just doesn’t work in my callback function. Damn.

[QUOTE=reaktor24;1286389]Thanks for that clear explanation. Seems simple enough.

Unfortunately I don’t get any ShaderProject.exe stack frames. All I can see is a list of 12 DLL frames.

I’ve just tried it from a couple of other points in my code and it does work correctly as you explained. It just doesn’t work in my callback function. Damn.[/QUOTE]

Not sure if this is your case but you could try to switch to another thread in your debugger. If the debugger is not in the same thread, it cannot see the matching callstack.

I keep getting errors about missing .pdb files if I try to step out of the callback function so I assume it must be something to do with that.

EDIT:

So anyway I’ve given up with the callstack and decided on a new (maybe unconventional) tactic. Basically I’ve created a new global variable called error_count which is a GLuint. It equals zero. Every time the debugCallback is called this value increases by one. Now by strategically inserting breakpoints around the program I have narrowed down exactly which calls are making the errors. Now I just have to fix the problems.

Will keep you updated on my progress. :slight_smile:

[QUOTE=reaktor24;1286392]I keep getting errors about missing .pdb files if I try to step out of the callback function so I assume it must be something to do with that.

EDIT:

So anyway I’ve given up with the callstack and decided on a new (maybe unconventional) tactic. Basically I’ve created a new global variable called error_count which is a GLuint. It equals zero. Every time the debugCallback is called this value increases by one. Now by strategically inserting breakpoints around the program I have narrowed down exactly which calls are making the errors. Now I just have to fix the problems.

Will keep you updated on my progress. :)[/QUOTE]

Quick Update:

First the good news. I have managed to fix all OpenGL errors! So that is quite good news.

More good news. I have a shadow on the screen!

I managed to get it to this state by reading this thread: https://www.opengl.org/discussion_boards/showthread.php/176958-Drawing-depth-texture-bound-to-a-FBO

I had made the same mistake as this guy but nobody here seemed to notice. The bind to the framebuffer has to occur BEFORE the glClear(GL_DEPTH_BUFFER_BIT) function.

OK now the bad news. The shadow is actually rotating with respect to the light orientation but it is also positioned incorrectly in the scene. i.e its not attached to the objects its meant to be shadowing. It must be something super obvious that I’m overlooking.

See this video to see the effect in action: https://www.youtube.com/watch?v=awKaZEOBy9Y

OK I think it is close to being finished. I have modified my transformation code on my cube object like this:

First the main rendering code


void RenderScene()
{
	glBindFramebuffer(GL_FRAMEBUFFER, shadowFBO);						// Select the framebuffer object first
	glClear(GL_DEPTH_BUFFER_BIT);										// Clear the depth buffer second
	light_frustum.UpdateCamera(&M_Viewing);
	glViewport(0, 0, 512, 512);
	UpdateProjection(60.0f, 512.0f, 512.0f, 1.0f, 1000.0f);
	M_LightPV = shadow_bias * M_Projection * M_Viewing;                           // NEW CREATION OF LIGHT POV MATRIX!
	glEnable(GL_CULL_FACE);
	glCullFace(GL_FRONT);
	CreateShadowMap();
	
	// SECOND RENDERING PASS...
	glBindFramebuffer(GL_FRAMEBUFFER, 0);								// Revert to the default framebuffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	camera.UpdateCamera(&M_Viewing);
	glViewport(0, 0, 1920, 1080);
	UpdateProjection(45.0f, 1920.0f, 1080.0f, 0.5f, 1000.0f);
	glDisable(GL_CULL_FACE);
	UpdateLightPosition();
	Draw3D();

Then the shadow matrix is constructed before each individual object is rendered in the second pass. Is this correct?


	mModelMatrix = mTranslationMatrix * mRotationMatrix;
	mModelViewMatrix = viewMatrix * mModelMatrix;
	mModelViewMatrix.GetMatrix(mv_Matrix);
	mModelViewMatrix.GetNormalMatrix(normal_Matrix);

	// Now we calculate the modelview-projection matrix
	mMVPMatrix = projectionMatrix * mModelViewMatrix;
	mMVPMatrix.GetMatrix(mvp_Matrix);

	// Calculate the normal matrix by taking the inverse-transpose of the modelview matrix
	mNormalMatrix = mModelViewMatrix;
	mNormalMatrix.InvertM();
	mNormalMatrix.TransposeM();
	mNormalMatrix.GetNormalMatrix(normal_Matrix);

	mat4 shadowMatrix = lightPVMatrix * mModelMatrix;
	shadowMatrix.GetMatrix(shadow_Matrix);			// NEW TEST!!

	glUniform3f(uLightAmbientLocation, light_ambient.x, light_ambient.y, light_ambient.z);
	glUniform3f(uLightDiffuseLocation, diffuse_light.x, diffuse_light.y, diffuse_light.z);
	glUniform3f(uLightSpecularLocation, specular_light.x, specular_light.y, specular_light.z);
	glUniform4f(uLightPositionLocation, light_position.x, light_position.y, light_position.z, light_position.w);

	glUniformMatrix4fv(uMVMatrixLocation, 1, GL_FALSE, mv_Matrix);
	glUniformMatrix4fv(uMVPMatrixLocation, 1, GL_FALSE, mvp_Matrix);
	glUniformMatrix3fv(uNormalMatrixLocation, 1, GL_FALSE, normal_Matrix);
	glUniformMatrix4fv(uShadowMatrixLocation, 1, GL_FALSE, shadow_Matrix);

The reason I ask is because the shadow appears to be at the correct ‘side’ of the object but is actually attached to the object and isn’t being projected onto the floor. I made another short video showing the program in action with the odd behaviour.

https://www.youtube.com/watch?v=Tqd4VlU0Xa0&t=26s

I’m almost there. If someone could help with this final problem that would be a massive help. Thanks.

OK I think I’m narrowing this down now but I still need a bit of help with this.

I’m pretty sure the problem lies in the creation of the depth map. i.e it’s not getting created properly.

I have tried texturing my world objects with the depth map just to see if it was created and there is no textured image in the depth map.

I am learning from the OpenGL 4 Shading Language Cookbook and it says just to pass through fragment shader and do nothing with it. So thats what I do.

vertex shader


#version 450 core

uniform mat4	mvp_Matrix;			// ModelViewProjection Matrix

in vec4			in_position;


void main()
{
	// Convert position to clip coordinates and pass to fragment shader
	gl_Position = mvp_Matrix * in_position;
}

fragment shader


#version 450 core

out vec4		frag_colour;


void main()
{
	// Do nothing, depth will be written automatically
}

Having looked at code on this tutorial I’m wondering now if I’m doing it wrong: http://ogldev.atspace.co.uk/www/tutorial23/tutorial23.html

He does this in his fragment shader


#version 330

in vec2 TexCoordOut;
uniform sampler2D gShadowMap;

out vec4 FragColor;

void main()
{
    float Depth = texture(gShadowMap, TexCoordOut).x;
    Depth = 1.0 - (1.0 - Depth) * 25.0;
    FragColor = vec4(Depth);
}