🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Getting Bounding Box For Sphere on Screen

Started by
10 comments, last by Hodgman 9 years, 6 months ago

Hey,

So I want to do a bit of optimization on my deferred renderer, in that currently I render all the lights as full screen quads, which wastes a lot of time on unnecessary pixels. Right now, all I have is point lights, so basically lights are represented with a position and a radius. I want to compute the bounding box for the sphere so that I can either render quads where the fragment shader is going to be preformed or tile-based shading, all though I'm not sure if tile based shading needs this kind of computation. Right now I've used an approximation algorithm to get the radius and the center on screen and then I can construct the bounding box by that. It goes something like this:


float rad = glm::atan(lightRad, screenSpacePos.z);
            rad = rad*(glm::max(ENGINE_WIDTH, ENGINE_HEIGHT) / glm::radians(RENDERENGINE_FOV));

It kinda works, but, like I said, its only an approximation, and when the camera is rotated, things that it covers becomes uncovered, so I need a more accurate representation. My thought was to construct a bounding box of the sphere in world space and translate it to clip space, get the min and max of all the points and construct a bounding box that way. Is there any way to do this more optimally? Or is this going to be one of the best ways to make sure that this is fairly accurate, as well as include other shapes ultimately (because bounding boxes can be calculated for those too).

Thanks.

Advertisement

For deferred with point lights you're probably better off drawing a light volume rather than using a full-screen quad plus scissor. Scissor test is specified to run after the fragment shader so your fragment shader will still be shading the entire screen (unless your driver can make a conformant optimization, but you shouldn't rely on that) and scissor test will only get you a saving on the final blends.

With light volumes you already have all the data you need (center and radius) so you can construct something like a slightly expanded icosahedron and send it through your regular 3D transforms. No need for anything fancy like scissor or stencil, the light volume geometry itself will ensure that you get a nice tight fit around the point light, giving you the best case for savings with per-fragment operations.

You may feel uneasy because an icosahedron has more vertices than a quad, but don't: there are going to be far more fragments than there are vertices, so you get a net saving.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

For deferred with point lights you're probably better off drawing a light volume rather than using a full-screen quad plus scissor. Scissor test is specified to run after the fragment shader so your fragment shader will still be shading the entire screen (unless your driver can make a conformant optimization, but you shouldn't rely on that) and scissor test will only get you a saving on the final blends.

With light volumes you already have all the data you need (center and radius) so you can construct something like a slightly expanded icosahedron and send it through your regular 3D transforms. No need for anything fancy like scissor or stencil, the light volume geometry itself will ensure that you get a nice tight fit around the point light, giving you the best case for savings with per-fragment operations.

You may feel uneasy because an icosahedron has more vertices than a quad, but don't: there are going to be far more fragments than there are vertices, so you get a net saving.

I meant to say that I was going to use render quads instead of scissoring. I had read that stencil testing was more expensive in the long run, rather than quad culling (rendering a quad to the screen and that the fragment shader is preformed on). I've updated the top post to reflect that.

Last time I did this, I just rendered a sphere biggrin.png I mean you're issuing a draw call anyway, who cares about a couple dozen extra polys...

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

I tried to do the screen space quads for spheres as well, but I gave up and just rendered them as spheres. Later on I found this which could be useful, https://www.shadertoy.com/view/XdBGzd

Derp

This article goes through the math of computing the area coverage of a sphere. It can also be used to calculate a bounding rectangle of that sphere projected onto screen:

http://www.iquilezles.org/www/articles/sphereproj/sphereproj.htm

Last time I did this, I just rendered a sphere biggrin.png I mean you're issuing a draw call anyway, who cares about a couple dozen extra polys...

And the sphere covers fewer fragments so it's potentially faster.

I had read that stencil testing was more expensive in the long run

I'm not entirely sure where your mention of stencil testing came from, so I'll leave it at this. Light volumes don't need stencil testing - there's a lot of misleading information out there suggesting that they do, but they don't.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This article goes through the math of computing the area coverage of a sphere. It can also be used to calculate a bounding rectangle of that sphere projected onto screen:

http://www.iquilezles.org/www/articles/sphereproj/sphereproj.htm

That looks really good, I'll take a look at it if there isn't a better method, honestly I think constructing a bounding box and doing what I described in the first post would be faster than all that computation, especially since I don't need a perfect sphere and the bounding box only needs to be calculated unless the sphere moves.

Last time I did this, I just rendered a sphere biggrin.png I mean you're issuing a draw call anyway, who cares about a couple dozen extra polys...

And the sphere covers fewer fragments so it's potentially faster.

I had read that stencil testing was more expensive in the long run

I'm not entirely sure where your mention of stencil testing came from, so I'll leave it at this. Light volumes don't need stencil testing - there's a lot of misleading information out there suggesting that they do, but they don't.

I had been under the impression that stenciling is much faster than rendering spheres to the screen, but I guess I'm wrong. I've kinda wanted to stay away from this because I might want to go into tile deferred shading, just because it seems the absolute fastest, even though my game isn't going to need 1024 lights at a time. The other problem with rendering quads and spheres is the blending, and in my experiments additive blending has cut my framerate in half.

I can't remember why, but I had decided not to use sphere rendering before, and I can't remember why. I'll look into it again though.

EDIT: Tried it and just remember why I decided not to use it. I rendered the geometry with additive blending and it doubled up because the back was showing through. I enabled back face culling, but when Im inside the sphere, it then culls out the sphere, so nothing is rendered. Any ideas?

EDIT: Tried it and just remember why I decided not to use it. I rendered the geometry with additive blending and it doubled up because the back was showing through. I enabled back face culling, but when Im inside the sphere, it then culls out the sphere, so nothing is rendered. Any ideas?

Either flip the culling mode when the viewpoint is inside the sphere, or else just use a regular full-screen quad for that case.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.


Either flip the culling mode when the viewpoint is inside the sphere, or else just use a regular full-screen quad for that case.

Nah, there's an easier way...


EDIT: Tried it and just remember why I decided not to use it. I rendered the geometry with additive blending and it doubled up because the back was showing through. I enabled back face culling, but when Im inside the sphere, it then culls out the sphere, so nothing is rendered. Any ideas?

Draw the back faces, not the front faces.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

This topic is closed to new replies.

Advertisement