according to the books that i've read stencil test is achieved by comparing a reference value with that of the stencil buffer corresponding to a pixel, how ever in one of the books it states that:
A mask is bitwise AND-ed with the value in the stencil planes and with the reference value before the comparison is applied
here i see a third parameter which is the mask, is this a mask related to the stencil buffer or it is another parameter generated by openGL itself??
can someone explain the comparison process and the values that have a role in this process??
glStencilMask (...) is used to enable or disable writing to individual bits in the stencil buffer. To make the number of parameters manageable and accommodate stencil buffers of varying bit-depth, it takes a GLuint instead of individual GLbooleans like glColorMask (...) and glDepthMask (...).
Typically the stencil buffer is 8-bits wide, though it need not be. The default stencil mask is such that every bit-plane is enabled. In an 8-bit stencil buffer, this means the default mask is 0xff (11111111b). Additionally, stenciling can be done separately for front/back facing polygons in OpenGL 2.0+, so there are technically two stencil masks.
In your question, you are likely referring to glStencilFunc (...), which also has a mask. This mask is not associated with the stencil buffer itself, but with the actual stencil test. The principle is the same, however; the above link details how this mask is AND'd together with the ref. value during testing.
A mask is an optional extra that sits between what is rendered and what it sent to be rendered.
Imagine you have a scene being rendered and you suddenly decide that you don't want any red being used by a certain object. You can use the mask to apply a bitwise operation to every pixel that object affects to remove the red values.
r:150 b:50 g:47 becomes r:0 b:50 g:47
r:13 b:255 g:255 becomes r:0 b:255 g:255
etc.
http://www.opengl.org/sdk/docs/man3/xhtml/glColorMask.xml should help explain it a bit more.
Related
I have created a shape in my stencil buffer (black in the picture below). Now I would like to render to the backbuffer. I would like one texture on the outer pixels (say 4 pixels) of my stencil (red), and an other texture on the remaining pixels (red).
I have read several solutions that involve scaling, but that will not work when there is no obvious center of the shape.
How do I acquire the desired effect?
The stencil buffer works great for doing operations on the specific fragments being overlaid onto them. However, it's not so great for doing operations that require looking at pixels other than the one corresponding to the fragment being rendered. In order to do outlining, you have to ask about the values of neighboring pixels, which stencil operations don't allow.
So, if it is possible to put the stencil data you want to test against in a non-stencil format image (ie: a color image, maybe with an integer texture format), that would make things much simpler. You can do the effect of stencil discarding by using discard directly in the fragment shader. Since you can fetch arbitrarily from the texture (as long as you're not trying to modify it), you can fetch neighboring pixels and test their values. You can use that to identify when a fragment is near a border.
However, if you're relying on specialized stencil operations to build the stencil data itself (like bitwise operations), then that's more complicated. You will have to employ stencil texturing operations, so you're going to have to render to an FBO texture that has a depth/stencil format. And you'll have to set it up to allow you to read from the stencil aspect of the texture. This is an OpenGL 4.3 feature.
This effectively converts it into an 8-bit unsigned integer texture. That allows you to play whatever games you need to. But if you want to use stencil tests to discard fragments, you will also need texture barrier functionality to allow you to read from an image that's attached to the current FBO. But you don't need to actually use the barrier, since you should mask off stencil writing. You just need GL 4.5 or the NV/ARB_texture_barrier extension to be available, which they widely are.
Either way this happens, the biggest difficulty is going to be varying the size of the border. It is easy to just test the neighboring 9 pixels to see if it is at a border. But the larger the border size, the larger the area of pixels each fragment has to test. At that point, I would suggest trying to look for a different solution, one that is based on some knowledge of what pattern is being written into the stencil buffer.
That is, if the rendering operation that lays down the stencil has some knowledge of the shape, then it could compute a distance to the edge of the shape in some way. This might require constructing the geometry in a way that it has distance information in it.
I am not clear why sometimes choose some specific bits of the stencil buffer to do stencil test. I cannot find examples like only test 1,3,5 bits of one stencil buffer.
The reason is not especially interesting. The stencil buffer usually contains 8 bits per sample, and you're free to use those 8 bits however you like in your application. So the meaning of those bits is up to you.
Often they're used for doing volume intersection tests, such as shadow volumes for stencil shadows (a technique popular circa 2005), where you might use the stencil buffer as a counter. Another example is deferred lighting, where you use a single bit in the stencil buffer to track which pixels are affected by a particular light.
So if you store "this pixel is affected by light #3" in bit 1, then you test bit 1 when you're rendering light #3. It's all up to the application developer.
I'm using the stencil buffer for two jobs. The first is to allow masking to happen, and the second is to write masks for objects that can be 'seen' through. In this particular case, the reserved bit is 0x80, the very last bit in the byte, with the rest left for regular masking.
The first purpose requires that the buffer be cleared after around 127 uses, or else past stencils will become "valid" again when testing, since the value must wrap back to 1. The second purpose requires the reserved bits in the buffer to stay alive through the entire frame.
Is there any way to clear the entire stencil buffer, while keeping the reserved bits set?
Your theory in the comment is correct. glStencilMask() is applied to the values written by glClear() and glClearBuffer().
From section "17.4.3 Clearing the Buffers" in the OpenGL 4.5 spec (emphasis added):
When Clear is called, the only per-fragment operations that are applied (if enabled) are the pixel ownership test, the scissor test, sRGB conversion (see section17.3.9), and dithering. The masking operations described in section 17.4.2 are also applied.
Where section 17.4.2 is titled "Fine Control of Buffer Updates", and includes the documentation of glStencilMask(). For glStencilMaskSeparate(), which is a more general version of glStencilMask(), it even says explicitly:
Fragments generated by front-facing primitives use the front mask and fragments generated by back-facing primitives use the back mask (see section 17.3.5). The clear operation always uses the front stencil write mask when clearing the stencil buffer.
So to clear the bottom 7 bits of the stencil buffer, you can use:
glStencilMask(0x7f);
glClear(GL_STENCIL_BUFFER_BIT);
I'm not sure if this is possible to do, but it's worth a shot. I'm using the stencil buffer to reduce overdraw for light volumes in a deferred renderer using this algorithm (when the camera is outside the volume):
Using a cheap shader, draw back faces with depth testing set to LEQUAL, marking them in the stencil buffer.
Using the expensive lighting shader, draw front faces with depth testing set to GEQUAL.
This will cause only pixels within the light volume to be shaded. The problem with this comes when drawing multiple lights. First, since state changes are expensive, it's probably not the best idea to repeatedly switch between the cheap and expensive shader for each light. Ideally I'd like to take advantage of all 8 bits of the stencil buffer by rendering 8 light volumes with the cheap shader followed by 8 light volumes with the expensive shader. However, issues arise when lights overlap, as there's no way to tell which pixels belong to which lights.
The solution that comes to mind would be to use 1 bit in the stencil buffer per light. So, for light n, mark the nth bit in the stencil buffer in the cheap pass, then only render pixels with that bit on during the expensive pass.
I haven't used the stencil buffer before, but from what I'm reading this doesn't seem possible. For this to work I'd have to set the stencil buffer using bitwise OR and the stencil function would have to be bitwise AND. However, the only operations on the stencil buffer I can see are: KEEP, ZERO, REPLACE, INCR, DECR, and INVERT, and the only functions are: NEVER, ALWAYS, LESS, EQUAL, LEQUAL, GEQUAL, GREATER, and NOTEQUAL.
Is there any way to somehow get this OR and ANDing behavior using the stencil buffer? And if not, is there an alternative approach to efficiently rendering light volumes?
To get ORing update behavior, use glStencilMask combined with GL_REPLACE. To get ANDing test behavior, use the glStencilFunc mask parameter combined with GL_EQUAL. In both cases, you'll want the ref parameter to glStencilFunc to be 0xff.
I'm not sure if this is possible to do, but it's worth a shot. I'm using the stencil buffer to reduce overdraw for light volumes in a deferred renderer using this algorithm (when the camera is outside the volume):
Using a cheap shader, draw back faces with depth testing set to LEQUAL, marking them in the stencil buffer.
Using the expensive lighting shader, draw front faces with depth testing set to GEQUAL.
This will cause only pixels within the light volume to be shaded. The problem with this comes when drawing multiple lights. First, since state changes are expensive, it's probably not the best idea to repeatedly switch between the cheap and expensive shader for each light. Ideally I'd like to take advantage of all 8 bits of the stencil buffer by rendering 8 light volumes with the cheap shader followed by 8 light volumes with the expensive shader. However, issues arise when lights overlap, as there's no way to tell which pixels belong to which lights.
The solution that comes to mind would be to use 1 bit in the stencil buffer per light. So, for light n, mark the nth bit in the stencil buffer in the cheap pass, then only render pixels with that bit on during the expensive pass.
I haven't used the stencil buffer before, but from what I'm reading this doesn't seem possible. For this to work I'd have to set the stencil buffer using bitwise OR and the stencil function would have to be bitwise AND. However, the only operations on the stencil buffer I can see are: KEEP, ZERO, REPLACE, INCR, DECR, and INVERT, and the only functions are: NEVER, ALWAYS, LESS, EQUAL, LEQUAL, GEQUAL, GREATER, and NOTEQUAL.
Is there any way to somehow get this OR and ANDing behavior using the stencil buffer? And if not, is there an alternative approach to efficiently rendering light volumes?
To get ORing update behavior, use glStencilMask combined with GL_REPLACE. To get ANDing test behavior, use the glStencilFunc mask parameter combined with GL_EQUAL. In both cases, you'll want the ref parameter to glStencilFunc to be 0xff.