Uniformly Darken Areas in the Scene Using a Triangle List, How? #1492
-
I have many things in my VSG scene. Some at ground level, some above. I have a triangle list, coplanar with the ground, that I'm currently using to color areas on the ground. You can think of it as shading where on the ground there are pipes and other features below the surface at all depths. So I draw the ground in the scene, then I draw the opaque triangles on top, then I draw the rest of the scene. Looks good. But what I really need is to use the color to "shade" the ground slightly where the triangles are, and not overlay it. So, I decided to enable blending. That doesn't work because many of the triangles are coplanar. When they are draw opaque, this isn't obvious because they just overwrite each other (I have depth test off). But, when I draw them semi-transparent, they blend the ground darker, but more so in areas with greater triangle overlap. I need a CONSISTENT blending across all pixels in the triangle list. I believe I'm going to need to do two passes for the scene to solve this, once to set the stencil buffer for areas where the triangles are, and then another to use the stencil pixels to blend a color with the existing pixels. Is this the only way to do this? Is there an easier way? If I wanted to do this two pass algorithm with the stencil buffer, how would I set this up in VSG? Note: I'm also using the ViewDependentState shadowing infrastructure, so I don't want to interfere with that. |
Beta Was this translation helpful? Give feedback.
Replies: 7 comments 5 replies
-
This sounds very much like the kind of situation the stencil buffer exists for, so that would probably be the most sensible approach. As a first attempt, I'd try adding state to the state group for your triangle list to disable depth and colour writes but enable stencil writes, then add another drawable that gets drawn later which does a stencil test and covers the whole screen with a single large triangle. It shouldn't be too complicated. |
Beta Was this translation helpful? Give feedback.
-
Wow! This would be INFINITLY easier to do than what I was going to do. Gosh, I hope this will work. Ok, so I first added a clear stencil to the scene graph early on with a:
Next, I turned off writing to the color buffer by:
Can't tell if this so far is working - though the black triangles are indeed not writing to the color buffer. Finally, I need to do the draw over the screen with a large rectangle using the stencil buffer as a guide. I'm pretty sure I know how to do exactly this EXCEPT how to get the geometry to fill the whole screen. The VSG examples use a different projection to make this easy. But I don't want to change my perspective projection. How do I create a flat sheet to cover my window viewport without changing my projection? I will have the scene elements added in order draw terrain using depth, clear stencil, draw triangles to stencil, draw rectangle blending using stencil, draw even more objects above the ground with depth. To do this, I need these child nodes in the scene together, so I don't want to create other camera, etc, if possible. |
Beta Was this translation helpful? Give feedback.
-
The easiest way is probably just to make a triangle with vertex coordinates at and render it with a vertex shader that just passes those coordinates straight through to the rasteriser. If you don't use the view or projection matrices, then the current view and projection details don't matter. |
Beta Was this translation helpful? Give feedback.
-
Interesting. But, up until now, I've let VSG handle most of the vertex/fragment shading (using the phong and flat shaders) because it knows about things like blending which I'll need in the final stencil blending step - though I guess I could do this too in the custom shaders. Also, why a triangle and not a quad? What is the 3 for? What are the raw coordinates of a quad fitting the four corners of the viewport? |
Beta Was this translation helpful? Give feedback.
-
The corners of the screen from the rasteriser's point of view range from -1 to 1, so to cover all of that with a single triangle, you need to go beyond the edge, and that's where the threes come from. It's pretty common that people suggest drawing a fullscreen quad instead of a single triangle, and it shouldn't make much difference here, but for more expensive effects, there are more cache misses and worse occupancy for the regions of the screen that cover the edges of the two triangles making up the quad, so it's better to get in the habit of using one big triangle. For something as simple as this, your shaders could simply be #version 450
layout(location = 0) in vec2 vsg_Vertex;
out gl_PerVertex{
vec4 gl_Position;
};
void main()
{
gl_Position = vec4(vsg_Vertex, 0.0, 1.0);
} for the vertex shader and #version 450
layout(location = 0) out vec4 outColor;
void main()
{
outColor = vec4(/* your colour here*/);
} for the fragment shader. |
Beta Was this translation helpful? Give feedback.
-
Wow! That vertex/fragment shader with the SINGLE triangle works! I got blending on the ground! This is SOOO much simpler than how I was going to do it. Thanks very much! |
Beta Was this translation helpful? Give feedback.
-
I have a problem, and I can't seem to track down why something drawn earlier in the scene graph would "show through" something later in the scene graph. All I'm trying to do is have shadow casting models in the scene on top of the terrain, but the "ground darkening" I'm doing using the stencil buffer is showing through. My scene graph looks like this:
I have used one of the VSG examples to write out the depth buffer and confirmed that up until #5, the scene only has depth for round Sun and terrain. The depth buffer isn't affected by the stencil buffer darkening process. But, even though the models are drawn very late (after skybox, sun, terrain, shadow darkening sequence), all use the depth buffer, and none use the stencil buffer, the darkened areas are STILL BLEEDING THROUGH THE MODELS. What am I missing? Anything I can check to track this issue down? |
Beta Was this translation helpful? Give feedback.
The corners of the screen from the rasteriser's point of view range from -1 to 1, so to cover all of that with a single triangle, you need to go beyond the edge, and that's where the threes come from. It's pretty common that people suggest drawing a fullscreen quad instead of a single triangle, and it shouldn't make much difference here, but for more expensive effects, there are more cache misses and worse occupancy for the regions of the screen that cover the edges of the two triangles making up the quad, so it's better to get in the habit of using one big triangle.
For something as simple as this, your shaders could simply be