Calculating scissor region for deferred lighting

Started by
18 comments, last by Nairou 12 years, 7 months ago
I've been implementing deferred shading, and have finally got it working. However, as expected, performance is terrible when the number of lights increases, as every light is currently being rendered as a full-screen quad.

I'd like to limit the the rendering of each light using a scissor region, but I'm having trouble understanding how to calculate the screen-space region affected by the light. I've been trying to follow this tutorial, which is the only source I can find that talks about using scissor testing for deferred shading, but it isn't the easiest to understand.

Does anyone have better references or explanations on how to calculate the region to scissor for a given light? I'm also open to other techniques besides scissor tests, but since I'm already using scissor testing, it seemed a good fit.
Advertisement
I too am interested in a good resource for this, although I think I have a good idea of how to acheive it. Currently I am only using a simple radius check in the frag. However, since doing 3d picking I think I've realized a different approach. If you take the view_matrix (camera_matrix) and the projection_matrix and find the corners of affect like this:

vec4 top_right_light_position = projection_matrix * view_matrix * vec4(light_position.x + light_radius, light_position.y + light_radius, light_posiion.z + light_radius, light_position.w);
vec4 botom_left_light_position = projection_matrix * view_matrix * vec4(light_position.x - light_radius, light_position.y - light_radius, light_posiion.z - light_radius, light_position.w);

You then know the bounds for the rectangle by using x, y, of each corner and can define a scissor rectangle. Although I'm sure there's a much better way to do this, and I haven't yet tested this. Just figured I'd give you some inspiration to get the wheels turning.
Douglas Eugene Reisinger II
Projects/Profile Site
You can just use a sphere / cube to approximate the light's area of effect. Set the radius of the sphere to encompass the radius of the light (probably in the vertex shader). I'm not sure how that compares to using scissor testing, but it should be faster than a fullscreen quad.
The fullscreen quad is the worst of course...

But with the radius check and what you're saying the vertex and fragment shaders still touch every pixel for lighting.

The scissor op removes those pixels that are not needed.

It's significantly faster I think.
Douglas Eugene Reisinger II
Projects/Profile Site
What I have read is really nice, is to chop the screen up into multiple scissor tests. Take the screen chopped into a 2x2 grid say. And you figure out which lights are present in each on screen grid. So you have to do some BSP type tests or something. Once you know each of those, you draw a quad over each grid, and not the fullscreen (the scissor test you dont need it now), and send all your lights in that grid to the shader at once. It does the lighting for all lights, instead of doing 1 light and blending with the main scene, then the 2nd light and blending with the main scene.

For their method though do what the other guy said and just draw a 3D box around the x,y,z of your light, at a specific size big enough to cover how far the light distance shines, and it will project onto the screen as the quad you want. Still wont need scissor testing as the pixels that the box projects to on screen are the only pixels that will be drawn and shaded anyway.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

It is really similiar to shadow volumes so you search for that name too I guess.

Basically you draw an enclosed model that will completely surround the light (it can be cube or a rough sphere). After while rendering this volume you use stencil operetors to find which pixels will be illuminated (or will be shadowed for shadow volumes)

There are 3 posiblities for a pixel depending on which sides of volume (front side or back side relative to camera) are rendered

  • If both sides are rendered (passed the depth test) then this pixel is behind the light and too far away. It won't be illuminated.
  • If back side is not rendered while front side is rendered that pixel is inside the light volume so it will be illuminated.
  • If both sides are not rendered (couldn't passed the depth test or maybe pixel is not on top of them) that it is not illuminated again.

You use stencil tests to find which pixels are inside the light. First render back side of model by culling front (of course don't render anything to depth buffer or color buffer. just stencil) And set a stencil bit to 1 if depth test fails. After this step stencil bit will be 1 for each pixel that is infront of back side of light volume. After that render front side of light volume and render light if depth test passes and stencil bit is 1. This will ensure that you will be rendering only if your pixel is between two sides of light volume.

alternatively you can use two sided stencil tests. Increase stencil buffer while rendering front and decrease it while rendering back. If a stencil buffer is 1 in the end it means that only the front side is rendered and pixel will be illuminated. Finally render a full screen quad to render light
Thanks for the shadow volume comments. I'm still hoping to find a solution using scissor regions, but I may have to give that a try.

I've started trying to read the "Scissor Optimization" chapter from the Mechanics of Robust Stencil Shadows article on Gamasutra, which deals exactly with the problem I'm having of using scissor regions to limit light rendering. However, I so far haven't been able to follow along very well. The article makes assumptions and pulls in equations that I don't know about, and doesn't really explain what its doing or why the equations are important.

I really want to understand the "why" of what I'm doing, and not just copy/paste math equations, so I'm still searching for solutions...
Drawing spheres as we suggested IS scissor testing. Just draw a sphere, where your light is, and the only pixels that will be be lit are the ones that the sphere projects to on screen.

[color="#1C2837"]However, as expected, performance is terrible when the number of lights increases, as every light is currently being rendered as a full-screen quad.[/quote]
[color="#1c2837"]I think you missed the deferred rendering memo. You draw a sphere for each light. When you really need to optimize, you draw portions of your screen with multiple lights at once using scissor tests:

[color="#1c2837"]Assuming 8 lights in your scene:

[color="#1c2837"]1.Draw sphere, sphere projected on screen will basically give you the "scissor pixels" the only ones the light will effect.
[color="#1c2837"]2. Light those pixels and ADD blend them to the scene.
[color="#1c2837"]3. Step 1 for next light.

[color="#1c2837"]8 Blend operations.

[color="#1c2837"]Optimized
[color="#1c2837"]1. Figure out (like that mechanics article, or basic ray tracing) what lights are in what part of your screen image.
[color="#1c2837"]2. Assuming your screen is cut in 4, say 2 lights are in each quadrant. You draw 4 quads, upperleft, upperight, etc. And send to your pixel shader 2 light locations for each quad you draw (the lights that actually are projected on screen and only light/influence those pixels in 1 specific quadrant).
[color="#1c2837"]3. Light those pixels and ADD blend them to scene.
[color="#1c2837"]4. Step 1 for next quadrant.

[color="#1c2837"]4 Blend operations. Because you calculated lighting for 2 lights at once.


[color="#1c2837"]For now just settle with the first version 8 blends.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal


Drawing spheres as we suggested IS scissor testing. Just draw a sphere, where your light is, and the only pixels that will be be lit are the ones that the sphere projects to on screen.

[color="#1C2837"]However, as expected, performance is terrible when the number of lights increases, as every light is currently being rendered as a full-screen quad.

[color="#1c2837"]I think you missed the deferred rendering memo. You draw a sphere for each light. When you really need to optimize, you draw portions of your screen with multiple lights at once using scissor tests:
[/quote]
What you're describing is using stencil testing, right? Correct me if I'm wrong, but isn't that just another method of doing the same thing as screen-space scissor testing? I don't understand why you would need both. Stencil test would show you exactly where to render based on the "shadow" created by the sphere geometry, but requires an extra pass to render the sphere geometry. Scissor test limits rendering to a particular rectangle on the screen, with no extra pass, but requires some fancy math to calculate the extent of the light on the screen. End result should be roughly the same either way.
I've started trying to read the &quot;Scissor Optimization&quot; chapter from the <a href='http://www.gamasutra.com/view/feature/2942/the_mechanics_of_robust_stencil_.php?page=6' class='bbc_url' title='External link' rel='nofollow external'>Mechanics of Robust Stencil Shadows</a> article on Gamasutra, which deals exactly with the problem I'm having of using scissor regions to limit light rendering. However, I so far haven't been able to follow along very well. The article makes assumptions and pulls in equations that I don't know about, and doesn't really explain what its doing or why the equations are important.<br /><br />I really want to understand the &quot;why&quot; of what I'm doing, and not just copy/paste math equations, so I'm still searching for solutions...<br />


That article is self-contained. The only assumptions it makes is that you know what a plane is and what a dot product is, and it does not pull in equations from out of nowhere. If you really want to understand how to calculate the proper scissor rectangle for a light source, then that article is the right place to look.

This topic is closed to new replies.

Advertisement