PDA

View Full Version : Render stencil to texture



nachovall
04-16-2009, 08:28 AM
Hi all

I'm trying to render the values of the stencil in a texture using FBO. Following the EXT_packed_depth_stencil (http://oss.sgi.com/projects/ogl-sample/registry/EXT/packed_depth_stencil.txt) especification I write that code:



glEnable(GL_TEXTURE_RECTANGLE_ARB);

//depth stencil texture
glGenTextures(1, &depthStencilTexID);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, depthStencilTexID);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH24_STENCIL8_EXT, SCREEN_RES_X, SCREEN_RES_Y, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);

//Color texture
glGenTextures(1, &colorTexID);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, colorTexID);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, SCREEN_RES_X, SCREEN_RES_Y, 0, GL_RGB, GL_FLOAT, NULL);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);

glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);

glStencilFunc(GL_ALWAYS, 0, 0);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);

glGenFramebuffersEXT(1, &fboID);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, colorTexID, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, depthStencilTexID, 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, depthStencilTexID, 0);

glClearColor(0.0,0.0,0.0,0.0);
glClearDepth(1);
glClearStencil(0);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

//that scene is just a part to deduce my problem
glColor3f(1,0,0);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,0);
glVertex3f(0.5,0,3);
glVertex3f(0.5,0.5,6);
glEnd();

glColor3f(0,1,0);
glBegin(GL_TRIANGLES);
glVertex3f(0,0,1);
glVertex3f(0.5,0,2);
glVertex3f(0.5,0.9,7);
glEnd();

glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

glDisable(GL_STENCIL_TEST);


That way stencil values are stored in my depthStencilTexID. Now I want to read the stencil values from a fragment shader, just drawing a GL_QUAD of all the screen to activate all shaders:



glClearColor(0.0,0.0,0.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

stencilFilterShader.enableProfile();
stencilFilterShader.bindProgram();

float value = (float)popularPlaceValue;
cgGLSetParameter1fv(popularPlace, &value);
cgGLSetTextureParameter(depthStencilTexture, depthStencilTexID);
cgGLEnableTextureParameter(depthStencilTexture);

glColor4f(1.0,1.0,1.0,1.0);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex3f(-1,-1,0);
glTexCoord2f(SCREEN_RES_X,0); glVertex3f(1,-1,0);
glTexCoord2f(SCREEN_RES_X,SCREEN_RES_Y); glVertex3f(1,1,0);
glTexCoord2f(0,SCREEN_RES_Y); glVertex3f(-1,1,0);
glEnd();

cgGLDisableTextureParameter(depthStencilTexture);
stencilFilterShader.disableProfile();


The specification of EXT_packed_depth_stencil says that the format of UNSIGNED_INT_24_8_EXT texture is:

31-------------------------------8-7--------------0
+----------------------------------+---------------+
| 1st Component | 2nd Component |
+----------------------------------+---------------+

I'm trying to acces the stencil value in my texture in that way:
float stencilValue = texRECT(depthStencilTexture, iCoord.xy).y;
because is the second component. I don't know if I'm rigth but it doesn't works as I expected. I'm doing something wrong?

Thanks.

martinsm
04-16-2009, 08:59 AM
You can not read stencil values in fragment shader. It is written in EXT_packet_depth_stencil spec - "The stencil index texture internal component is ignored if the base internal format is DEPTH_STENCIL_EXT".

nachovall
04-16-2009, 09:32 AM
You can not read stencil values in fragment shader.

I'm not reading the stencil value from the stencil buffer. I'm rendering to texture the stencil value and then, read the texture value in my fragment shader.

Anyway, if I understand your reply I should change the format of my texture. Isn't it?

martinsm
04-16-2009, 10:43 AM
I assume with this "texRECT(depthStencilTexture, iCoord.xy).y;" you want to read stencilvalue out of texture that is bound to depthStencileTexture sampler. Right? As I said before - it is not possible this way.

I do not know how to read stencil values - never needed such thing myself.

nachovall
04-16-2009, 10:56 AM
Why is not possible? When I render to texture attaching the GL_STENCIL_ATTACHMENT_EXT to a FBO I assume that the stencil value is stored in the attached texture.

glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH24_STENCIL8_EXT, SCREEN_RES_X, SCREEN_RES_Y, 0, GL_RGBA, GL_INT, NULL);


So, once I've rendered my scene to texture and unbind the FBO, why is not possible to get the stored value (stencil value)?

martinsm
04-16-2009, 12:16 PM
Of course it is possible to store stencil value like that. No doubts about that.
But EXT_packed_depth_stencil says that there is no way to retrieve that value in fragment shader using texture2D/Rect functions. It explicitly says that stencil value will be ignored in such case. This is what I am saying.

Jan
04-16-2009, 12:27 PM
Yep, pain in the butt.

I once had to visualize the content of a stencil buffer (count overdraw...), i simply rendered 50 times a quad, each time with a different stencil test, which was only passed for a given stencil value, such that i knew in the shader "if it passed the test in this render pass, the value is x".

Obviously this was only a solution, because speed was not an issue.

Jan.

nachovall
04-17-2009, 12:45 AM
OK. Now I understand what you mean martism. Thanks for your explanation.



i simply rendered 50 times a quad, each time with a different stencil test, which was only passed for a given stencil value, such that i knew in the shader "if it passed the test in this render pass, the value is x".


Yes, that's a solution but, as you say, is too slow. I'll find another way to get the same result.

Thanks so much for your replys.