Deferred lighting, light volumes and hard edges

I have recently been implementing deferred lighting/rendering in my DIY game engine, and most things have been going just fine, but now that I’m rendering my light volumes using actual geometry I’m finding that from some angles the light gets cut off with an hard edge, basically because the light volume does not cover the same pixels in the gBuffer from all angles.

Here are some screenshots to illustrate what I mean:

Here is an image of a basic crate object with a hard edge from a point light showing up on it.
[ATTACH=CONFIG]1721[/ATTACH]

And here is the color buffer of the same crate to show that noting else is occluding the light.
[ATTACH=CONFIG]1722[/ATTACH]

And this is a part of a simplistic render of all the point lights volumes in the viewport from the same viewpoint as before, and I have marked the point light edge that show up on the crate.
[ATTACH=CONFIG]1723[/ATTACH]

And lastly, here is a completely different image highlighting the problem in another way.
Here you can clearly see the problem on the left hand wall, but also that I have working attenuation calculations on the floor, and if i watch the effected wall from inside the room the light looks correct, but from this angle the point light “clips” the lighting early.
[ATTACH=CONFIG]1724[/ATTACH]

I was part of implementing a deferred lighting solution in school about a year ago, and I can’t remember having this issue back then, but it is quite possible that someone else solved this before I ever noticed.
And after thinking about this I can’t seem to figure out a solution to this problem, and my attempts to find information on dealing with this problem I come up dry.
So am I doing something wrong here, or is there a well known way of dealing with this problem that I’m missing?

[QUOTE=Dregel;1290659]…now that I’m rendering my light volumes using actual geometry I’m finding that from some angles the light gets cut off with an hard edge, basically because the light volume does not cover the same pixels in the gBuffer from all angles.

So am I doing something wrong here, or is there a well known way of dealing with this problem that I’m missing?[/QUOTE]

It’s not completely clear what your problem is here, particularly with you saying that this effect is angle dependent.

However, from your picture it reminds me of something I hit when implementing point light source in deferred shading. Namely, you need to make sure that your light source illumination fades to 0 before you hit bounds of the light source bounding primitive, so you don’t see artificial lighting edge effects in your scene from the lighting implementation.

For point light sources with cones, D3D9’s spotlight interface is useful here. Namely, you specify a cone angle range over which the light source illumination fades to zero. Your light source bounds should be at or past the outer cone. You need a similar concept for distance (a range over which the illumination fades out to 0). Your light source bounds needs to be at or past the outer distance. Otherwise you’re going to see hard edges in your scene lighting which shouldn’t be there.

Yeah, I realize my explanation of the issue is probably quite hard to follow, and I might have been wrong in calling it an angle based problem, but I’m not quite sure how to explain this problem. :stuck_out_tongue:
To calculate the attenuation in the shader, i use this line of code, so my illumination SHOULD correctly fade from 1.0 to 0:


//light_scale = radius of point light sphere model
float attenuation = smoothstep(light_scale, 0.0f, length(light_position - fragment_position));

But here is a short video that I hope will help to clarify the issue some.
https://youtu.be/xz-rsWVizM0

On the left hand side of the video video you can see the hard edge of the point light appear and disappear as I orbit around the model.
The quick “flashes” are me quickly swapping to rendering the point light volume instead of the scene to try and show the relationship between the viewport/angle and the point light geometry.
And at the end I show the linearized representation of my depth buffer just to prove that no other object is occluding the view.

Your smoothstep() looks a little odd to me. With the prototype being “smoothstep( edge0, edge1, x )”, your x is clearly non-negative, and edge1 is zero. The implication is then that edge0 is non-negative. This implies edge0 >= edge1. The smoothstep() results are undefined in this case.

Perhaps you want something like:


float attentuation = 1 - smoothstep( 0.0f, light_scale, length( light_position - fragment_position ) );

Wow… I’m not sure how I managed to mess that up…
You’re absolutely right, and now I’ve got that fixed, thank you! :slight_smile:

But the problem still remained after this, but I did have a sudden epiphany that, because I’m sending in the scale factor of the light volume mesh to use in light calculation, i needed to divide that by 2.0 in order to get the correct radius, and that solved the problem! :stuck_out_tongue:
So I have been doing all my calculations as if the light volume was twice the size it actually was, and that results in some really weird behaviour! :slight_smile:

Thanks for all the help Dark Photon! :slight_smile:

Now, where’s that damned rubber duck when you need it…