OpenGL 4 Shadow Map Problem

Started by
4 comments, last by Palidine 9 years, 3 months ago

Hey,

Back again for what is likely just a trivial error. I am doing some basic & standard Shadow Map rendering.

  1. geometry only pass writing to a FBO depth_buffer
  2. second pass comparing fragment depth in light space against the depth_buffer

Problem: I'm nearly positive that I am either (a) not actually writing to depth_buffer or (b) failing to bind it to the second pass fragment shader correctly for reading

Shadow Map Initialization


glGenFramebuffers(1, &shadowmap_framebuffer);
	glBindFramebuffer(GL_FRAMEBUFFER, shadowmap_framebuffer);

	glGenTextures(1, &shadowmap_texture);
	glBindTexture(GL_TEXTURE_2D, shadowmap_texture);
	glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT32, shadowmap_size,shadowmap_size, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
		 
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowmap_texture, 0);

	// No color output in the bound framebuffer, only depth.
	glDrawBuffer(GL_NONE);
	glReadBuffer(GL_NONE);

	// check that our framebuffer is ok
	ASSERT( glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE );

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

First-Pass shadow render

I've completely eliminated everything except the depth clearing just to sanity check things

c++ side code:


	glBindFramebuffer(GL_FRAMEBUFFER, shadowmap_framebuffer);
	glViewport(0,0,shadowmap_size,shadowmap_size);
	glClearColor(0.f,0.f,0.f,1.f);
	glClearDepthf(1.f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glViewport(0,0,screenInfo.Width,screenInfo.Height);

Second-Pass depth read

relevant c++ side code


	glActiveTexture( GL_TEXTURE3 );
	glBindTexture( GL_TEXTURE_BUFFER, shadowmap_texture );

fragment shader


#version 440

layout(binding=3) uniform sampler2DShadow shadowMap;

in vec4 ex_ShadowCoord;

out vec4 outColor;

void main()
{
	//shadow
	//let's just read something that should be valid
	//and also which should definitely pass. If the shadowMap is being cleared to 1.f
	//then a lookup with a z == 0.0 should always return 1.0 from texture(...)
	vec3 lookupVec = vec3(0.5,0.5,0.0);
	float depth = texture( shadowMap, lookupVec );
	float visibility = mix( 0.5, 1.0, depth );

	//
	// VALIDATE shadowMap
	//
	vec3 color = vec3(0.0,0.0,0.0);
	if ( depth == 0.0 )
		color.r = 1.0;
	else if ( depth == 1.0 )
		color.b = 1.0;
	else
	{
		color.r = 1.0;
		color.g = 1.0;
	}

	outColor = vec4( color, 1.0 );
}

Everything is drawing completely RED which means that the texture(...) call is failing at least how I understand it should work. That suggests to me that it's mostly likely not bound correctly (based on prior errors I've made) or perhaps less likely it's not getting written to ever.

I've otherwise validated that the rest of the pipeline is correct (ex_ShadowCoord is coming in correctly and I have full coverage of the scene being rendered)

Advertisement
I would be surprised if you saw red because you have specifically told OpenGL not to draw anything by calling ::glDrawBuffer( GL_NONE );.
Both ::glDrawBuffer() and ::glReadBuffer() should be removed from your code; they are unrelated to shadowing.

Furthermore, you haven’t created any GL_TEXTURE_BUFFER’s. shadowmap_texture is a 2D texture and ::glBindTexture() should be passed GL_TEXTURE_2D.

Where are your calls to ::glGetError()?


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

Furthermore GL_DEPTH_COMPONENT32 may not work (i dont know why my geforce gt 520 doesnt want to use 32bit depthbuffer and when i try to use it whole driver cracks)

and

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);

is iuseless since you are not using hardware extension for comparsion but shader.

now whats below i am possibly wrong

but

glBindTexture( GL_TEXTURE_BUFFER, shadowmap_texture ); should you use GL_TEXTURE_2D in your case?

Hey,

A couple of good directions, thanks. WiredCat and Spiro, the GL_TEXTURE_BUFFER -> GL_TEXTURE_2D solved the immediate problem and the second pass is now apparently able to read the shadowMap.

Spiro, I think I either pruned my code too much or didn't explain what was going on sufficiently. The reason it's rendering is that you're only looking at the FBO def for the first-pass which is a depth-only write pass. There is a second pass that has been working totally fine for quite a while that's actually doing the rendering. I'm trying to wire the depth from the first pass (rendered ortho from the skylight) into the fragment shader for the second pass (rendered perspective from the camera) so that I can do shadow maps. The calls to glDrawBuffer/glReadBuffer only affect the FBO that's set up for the depth rendering and so are fine, I'm nearly certain, since no color information is being written in that pass.

There are more problems now (it seems depth isn't written correctly now during the first pass) but I'll debug for a while and come back with either my solution or more questions. Meanwhile if there's anything obvious there relating to depth not being written in the first pass, let me know smile.png The shaders for that pass are just trivial pass throughs and the fragment shader is empty since nothing is being done since all I care about is the automated depth writing.

If it's helpful, I've been following this old old old tutorial. I'm probably running in to either dumb math errors (typical), more lame copy/paste errors like the above, or maybe openGL 1.2 -> 4.x problems:

http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/

PS, Wired:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);

is iuseless since you are not using hardware extension for comparsion but shader.

Are you sure this is correct? The openGL 4 documentation of glTexParameter and also the documentation of the GLSL texture(...) calls both suggest this is necessary for texture(...) to be able to make the depth check correctly from a sampler2dshadow

https://www.opengl.org/sdk/docs/man/docbook4/xhtml/glTexParameter.xml

https://www.opengl.org/sdk/docs/man/html/texture.xhtml

http://stackoverflow.com/questions/22419682/glsl-sampler2dshadow-and-shadow2d-clarification

Granted that tutorial is quite old, so I could just be wrong here smile.png

ok. Actually after making hte GL_TEXTURE_BUFFER -> GL_TEXTURE_2D change shadow maps are totally working! Woo! The other thing that was going on, for the curious, is that I had the Z-Clip plane on my orthographic transform for the depth-writing pass set WAY to high so I was washing out the signal with much too far a clip plane. Basically losing important resolution on my floating point depth value since I was brute forcing a clip from [0 .. FLT_MAX]. Setting the far clip plane to just beyond my scene makes it all happy.

This topic is closed to new replies.

Advertisement