2
\$\begingroup\$

I'm trying out deferred rendering and I'm using the tutorials at http://ogldev.atspace.co.uk. I've got the basics working and I'm currently trying to implement the final step from tutorial 37 (http://ogldev.atspace.co.uk/www/tutorial37/tutorial37.html). In the previous tutorial, the author explains how to render point lights as spheres in a second render pass, combing the effect of the lights with the data generated in the geometry buffers in the first pass, and I've got this working already.

In tutorial 37, he explains how to use the stencil buffer to limit the influence of the lighting to only light up objects actually inside the light sphere. He describes how the stencil buffer is set up to decrease the stencil value when the depth test fails for front facing polygons and increase it for back facing polygons, resulting in the stencil buffer containing zeroes for all pixels belonging to objects outside the light sphere (as these will either be in front of the light sphere, leading to the depth test failing both for the front facing and the back facing polygons of the lights sphere, causing the stencil value to first decrease by one and then increase by one, or behind it, leading to neither front facing nor back facing polygons of the light sphere failing the test so the stencil value remains unchanged). Objects inside the sphere though cause the depth test to fail only for back facing polygons, leading to the stencil value being not zero. This will later be used to only render the light sphere on pixels for which the stencil value is not zero.

So far, so good. But then there is a remark saying that the case when the camera is inside the light sphere is left as an exercise for the reader, and this comment puzzles me. Won't it still work the same way? If the camera is inside the light sphere, then objects in front of the light sphere will not be rendered at all (since they are behind the camera). Objects behind it will still not cause the depth test to fail for the back facing polygons of the light sphere (and the front facing polygons will of course not be rendered) so the stencil values for those pixels will still be zero. As for objects inside the light sphere, the depth test for the back facing polygons will fail, causing the stencil value to be different from zero. It seems to me that no special consideration will need to be taken for the case when the camera is inside the light sphere, but maybe I'm missing something. Can someone please help me figure this out?

\$\endgroup\$
1
\$\begingroup\$

This method uses geometric shapes to represent volumes of light. The outline of a sphere, viewed from any angle, is a circle. "Selecting" the pixels within that circle is the primary reason for using geometry in this way; this method only invokes the light shader on the pixels within the circle rather than testing every pixel on the screen, many of which may be unaffected by the light source being rendered.

His comment applies to the final pass (using typical back-face culling), and not to the initial pass (with culling disabled).

When you are "inside" the light volume, the front faces are behind you (culled) and the backfaces are reverse-wound (culled). Since no fragments are generated, the stencil value is never used.

Your exercise was to realize/determine that you need to reverse the culling direction in order to draw the backfaces, instead. If you are outside of the volume, both cull-modes produce the same circle, so it's just as easy to always render back-faces for the last pass.

This is the "changelog" for the affected shader (about 3/4 down the page):

Same as the other passes the point light pass starts by setting up the G buffer for what it needs (by calling GBuffer::BindForLightPass()). It sets up the stencil test to pass when the stencil value is not equal to zero. After that it disables the depth test (because we don't need it and on some GPUs we may get some performance by disabling it) and enable blending as usual. The next step is very important - we enable culling of the front face polygons. The reason why we do that is because the camera may be inside the light volume and if we do back face culling as we normally do we will not see the light until we exit its volume. After that we render the bounding sphere as usual.

\$\endgroup\$
0
\$\begingroup\$

It might be worth taking a look at the difference between depth pass and depth algorithms for the shadow volumes rendering (https://en.wikipedia.org/wiki/Shadow_volume) since the problem is similar IIRC. It might be easier to convince yourself with the shadows.

You have some pictures here http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/the-theory-of-stencil-shadow-volumes-r1873, there is also a tutorial at ogldev (40th).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.