Deferred lighting

Started by
7 comments, last by MJP 12 years, 11 months ago
I'm representing point lights as screen aligned quads in my deferred renderer but I have the problem of them not being drawn when the centre of the light is behind the camera (its effects should still be visible).

I understand that I need to "move" the quad to the back of the light's area of effect in relation to the camera but I can't figure out how to do this. Can anyone enlighten me? Thanks!
Advertisement
You either use a bounding sphere instead of a screen aligned quad or you change the depth function.

My advice is to use a bounding sphere because its more precise and changing the depth function might be expensive.
Just offset the quad's depth by the light source radius. If you *aren't* using billboarding (and if you are, why?) then all you need to do is plop the offset in the vertex shader and call it a day :)
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
Thanks for the replies!

I'm aware that I need to offset the quad's depth by the radius but I can't get it to work correctly for some reason. This is what I'm doing:



Vertex shader:

VS_OUTPUT main( VS_INPUT input )
{
VS_OUTPUT output;

// Transform light position to view space
float4 position_VS = mul( float4( input.position, 1) , view_xform);

// Get the light's z component in view space
float light_z_VS = position_VS.z;

// Transform light position to screen space
output.hPosition = mul( position_VS, proj_xform );

// Determine the screen space dimensions of the quad
float4 quadSize = { input.range, input.range, light_z_VS, 1 }; // I tried adding input.range to light_z_VS here (which I think makes sense as it's in view space), which didn't work.
quadSize = mul( quadSize, proj_xform );
output.quad.x = quadSize.x/quadSize.w;
output.quad.y = quadSize.y/quadSize.w;

// Pass these straight through...
output.colour = input.colour;
output.wPosition = input.position;
output.range = input.range;
output.intensity = input.intensity;

return output;
}

Geometry shader:

{
...
float4 screenPos = input.hPosition;
float2 quadSize = vertex[0].quad*screenPos.w;

float4 quad[] =
{
{ screenPos.x+quad.x, screenPos.y-quad.y, screenPos.z, screenPos.w },
{ screenPos.x+quad.x, screenPos.y+quad.y, screenPos.z, screenPos.w },
{ screenPos.x-quad.x, screenPos.y-quad.y, screenPos.z, screenPos.w },
{ screenPos.x-quad.x, screenPos.y+quad.y, screenPos.z, screenPos.w }
};
...
}


Anything obviously wrong with what I tried? Adding on the radius in any other coordinate space doesn't make sense to me.

Using HLSL with D3D10 BTW.
Few bits that stick out for me-- Z does not change in the projection transform. You might be able to optimize your shader for superscalar GPUs (like modern nVidia stuff) by just scaling the radius accordingly instead of going through a whole matrix transformation. Second: define 'doesn't work' here. Though the fault is mine for not asking this initially, are you sure that clipping is your problem? Try enabling wireframe display for your light quads and seeing what's going on.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
With the radius added, the light still disappears completely when behind the camera. Looking at it again I see that it also icnreases the size of the quad. I'll have a think about what that implies. (The quad is the correct size without adding an offset.)
Instead of using a quad, try using a sphere. I suggest checking out Humus' engine. He uses a deferred engine and spheres as point lights. http://humus.name/index.php?page=3D

Download the framework 3 at the top of the page, and check out the deferred shading 2 example.[size="5"]
Wisdom is knowing when to shut up, so try it.
--Game Development http://nolimitsdesigns.com: Reliable UDP library, Threading library, Math Library, UI Library. Take a look, its all free.
There's definitely research that says the additional precision/'ease' afforded by sphere geometry is in general outweighed by setup overhead-- if you want performance, the quads are the right way to go.
(btw, I believe there's a working quad implementation there, you can try and compare it to what you're doing and see if that helps)

EDIT: Stupid idea but you can also try the Naughty Dog tile trick they discuss in the presentation. That's probably even faster, come to think of it.
clb: At the end of 2012, the positions of jupiter, saturn, mercury, and deimos are aligned so as to cause a denormalized flush-to-zero bug when computing earth's gravitational force, slinging it to the sun.
Sphere's don't really buy you too much over quads, especially for lots of small point lights. Tiled will usually start out slower than quads or volumes for small numbers of lights, but as they scale up into the dozens or hundreds tiled will start to perform significantly better since it uses much less bandwidth.

This topic is closed to new replies.

Advertisement