Render to a luminance texture map

hello guys,

I need to implement the shadow map method. the first pass writes the depth information onto a framebuffer object.

since the depths are float numbers, i save them on to a luminance texture map, created with the following call:
glTexImage2D(GL_TEXTURE_2D,0,GL_INTENSITY,1024,1024,0,GL_LUMINANCE,GL_FLOAT,NULL);

the question is how should i write values to this texture map inside the shader?

i tired to use

gl_FragColor.w = value. and it seems wrong,

and

gl_FragColor.r seems work.

however, as i remember, when i need to access the values of a luminance texture map, i use this:

value = texture2D(map,texcoord).w;

so am i right? use .r to write and .w to read?

since the depths are float numbers, i save them on to a luminance texture map, created with the following call:

Was there something wrong with just creating a GL_DEPTH_COMPONENT24 texture, binding it as the depth buffer, and rendering nothing to the non-existing color buffers? That’s usually how lightmapping is done.

Alfonse you bring up some really interesting information here that I’ve been looking into. I’m looking into shadow maps and deferred rendering and was trying to figure out how to bind a depth map as a texture so I could draw the depth value out of it for defered rendering instead of having to bind an additional texture map just to store a z value. (figure it’s redundant since the depth buffer is already there anyhow)

Out of curiosity i bound a GL_DEPTH_COMPONENT24 texture map as the depth buffer to my FBO:

//glGenRenderbuffers(1, &id_FboDepth);
glGenTextures(1, &id_FboDepth);
glBindTexture(GL_DEPTH_COMPONENT24, id_FboDepth);
//glBindRenderbuffer(GL_RENDERBUFFER, id_FboDepth);
//glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, *width, *height);

glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, *width, *height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, id_FboDepth);
glBindRenderbuffer(GL_RENDERBUFFER, 0); // Unbind the render buffer

and ran some tests on it. Didn’t really seem to work under any of the permutations I tried out. (failed to do the depth test correctly) I’ve been paging through my orange and red book for info on this but can’t really seem to find much. The commented out lines are how I typically attach a Depth Buffer.

I noticed that you can’t just use
glBindTexture(GL_TEXTURE_2D, id_Depth_Renderbuffer);

I know you can bind depth components to shadow samplers, you need to for textureproj() functions, just trying to find the API code for it.

Looking into this more, are you suggesting that when you make a FBO, instead of binding a RenderBuffer object in the depth slot, instead you bind an additional texture with a depth format into a texture color attachment slot and use that instead as an output for your z coord? And as you get fragments, you do your own depth test right in the fragment shader using the bound depth texture buffer that you’re also writing to at the end?

Looking into this more, are you suggesting that when you make a FBO, instead of binding a RenderBuffer object in the depth slot, instead you bind an additional texture with a depth format into a texture color attachment slot and use that instead as an output for your z coord?

Yes.

And as you get fragments, you do your own depth test right in the fragment shader using the bound depth texture buffer that you’re also writing to at the end?

No. The depth buffer works just the same whether it happens to be a texture object or a renderbuffer object. Your fragment shader doesn’t even need to have inputs or outputs; it can just be “void main(){}”.

Note this code works, but two questions at the bottom.

Good stuff, I got this working this morning with a texture map, here’s some code:
(Note I attached a texture as well so you can render it from the camera view to verify the depth component is working)

// This is your texture depth buffer
glGenTextures(1, &id_FboDepth);
glBindTexture(GL_TEXTURE_2D, id_FboDepth);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, *width, *height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glBindTexture(GL_TEXTURE_2D, 0);

// This is optional, but it’s a texture for storing the pixels //as your camera sees the scene
glGenTextures(1, &id_FboTexture);
glBindTexture(GL_TEXTURE_2D, id_FboTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, *width, *height, 0, GL_RGBA, GL_FLOAT, NULL);
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_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindTexture(GL_TEXTURE_2D, 0);

// this binds it to the FBO:
glGenFramebuffers(1, &id_Fbo);
glBindFramebuffer(GL_FRAMEBUFFER, id_Fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, id_FboTexture, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, id_FboDepth, 0);

status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT ||
	//status == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS || // this is undefined for some reason
	status == GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT ||
	status == GL_FRAMEBUFFER_UNSUPPORTED)
{
	return false;
}

glBindFramebuffer(GL_FRAMEBUFFER, 0);

Note if you want to remove the image component of the FBO, just remove the id_FboTexture generation part and add:
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
to the part where the Framebuffer is bound to stop it from trying to write pixel data to the image buffer.

You can now bind the depth buffer as a texture.

[b]Question however: This is the format that they want when we use the textureProj function correct? They don’t want us to bind a renderbuffer to a sampler correct?

Also, the line:
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, *width, *height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
with the texture depth creation. The only part I couldn’t reason out is why we’re using GL_UNSIGNED_BYTE instead of something like GL_LUMINANCE which the GL spec recommends using for depth textures.[/b]

Stop randomly bold-facing parts of your post. Bold is for emphasis; it should be used sparingly.

They don’t want us to bind a renderbuffer to a sampler correct?

You can’t bind a renderbuffer to a sampler. Well you can if you use NV_explicit_multisample, but that’s an il-conceived extension that should never be used when at all possible.

The only part I couldn’t reason out is why we’re using GL_UNSIGNED_BYTE instead of something like GL_LUMINANCE which the GL spec recommends using for depth textures.

The last three parameters are for pixel transfers. By specifying a NULL pointer (and not having anything bound to GL_PIXEL_UNPACK_BUFFER), you are telling OpenGL not to initialize the data by doing a pixel transfer operation. So it doesn’t matter what the other two parameters are. You could pass 0, and it would be perfectly fine with that.

Also, the second parameter, the GL_UNSIGNED_BYTE is the type for the pixel transfer (if any). GL_LUMINANCE isn’t a type; it’s a format, like GL_DEPTH_COMPONENT.

Cripes I started reading your tutorial and pretty much everything in there that was learned the hardway that wasn’t mentioned in the Red or Orange book is on there so far. Just wanted to say cudos, and it should be on amazon for a kindle download.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.