PDA

View Full Version : How to perform incremental operations on a Stencil Texture?



stimulate
04-18-2017, 08:10 AM
I need to write to and read from multiple stencil buffer textures for my shadow volume implementation. Every light casts a shadow mesh behind every object in its light range, and the goal is to then render this shadow geometry of every light into a respective stencil texture. I will render the shadow geometry twice, first culling the backfaces and incrementing the stencil texture values for every front-facing fragment, then i cull the frontfaces and decrement the stencil texture values for every backface.

I have found it hard to find a way to create a stencil texture, thats why i have got it working with a single component texture, bound as a color attachment.



for (Lighting::LightShadows& shadows : Lighting::allLightShadows) {

glNamedFramebufferTexture(shadowFBO, GL_COLOR_ATTACHMENT0, shadows.stencilBuffer, 0); // attach the "stencil"-texture to framebuffer
glClear(GL_COLOR_BUFFER_BIT);

glCullFace(GL_BACK);
glUniform1i(glGetUniformLocation(ShaderProgram::ge tPointer()->ID, "cullMode"), 0); //tell the shader the culling mode
checkOpenGLErrors("After renderShadows()2.0");
glDrawElements(GL_TRIANGLES, shadows.indexCount, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * (Lighting::shadowIndexOffset + shadows.indexOffset)));


glCullFace(GL_FRONT);
glUniform1i(glGetUniformLocation(ShaderProgram::ge tPointer()->ID, "cullMode"), 1);
checkOpenGLErrors("After renderShadows()2.1");
glDrawElements(GL_TRIANGLES, shadows.indexCount, GL_UNSIGNED_INT, (void*)(sizeof(unsigned int) * (Lighting::shadowIndexOffset + shadows.indexOffset)));


}




The shader uses the depth buffer values of all my scene geometry to determine which fragments are in front of or behind the shadow volume, thus determining if the fragment should even be affected at all or not.

The problem i have is, that i can not read from and write to the same texture at the same time and therefore can not increment the texture values for the shadow volume frontfaces or decrement them for the backfaces.

I have seen code which seems to perform in-/decremental operations on stencil buffers, using glStencilOp, but how can i apply these operations to textures? Or is there another way to have multiple stencil buffers?

GClements
04-18-2017, 09:54 AM
I have seen code which seems to perform in-/decremental operations on stencil buffers, using glStencilOp, but how can i apply these operations to textures?
If you need to perform read-modify-write operations on a texture from within a shader, you can use image load/store (in this case, imageAtomicAdd()). This requires OpenGL 4.2 or the ARB_shader_image_load_store extension.



Or is there another way to have multiple stencil buffers?

Framebuffer objects. These only require OpenGL 3.0, but stencil-only textures were only added in OpenGL 4.4 (from the ARB_texture_stencil8 extension). With earlier versions, you either have to use a renderbuffer as the stencil attachment or use a depth+stencil texture (which requires significantly more memory).

If you use a renderbuffer, you can't access the contents as a texture (or image); you would need to use glReadPixels() to extract the contents (ideally to a pixel buffer object rather than to client memory). But fixed-function stencilling may be more efficient than emulating it using image load/store.