Sign in to follow this  

Determining which lights are "important" for an object

This topic is 4094 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello there! I guess, the topic pretty much explains what I´m wondering about. Currently I have implemented a simple deferred renderer and therefore have "evaded" that problem, but I am thinking about implementing a forward renderer, too, and therefore encounter that problem again: If I have a scene consisting of about 60 to 100 objects (only complete meshes, no polygon soup or something like that) and have about 30 lights in the map or something like that, I obviously need to determine which lights should be used to render a certain object, e.g. which lights have the most impact on the look of the object. That "the most impact" part is where I´m having problems. Imagine a scene with an ambient light and a directional light, add to this a big, but not too bright point light and a spot light with a narrow cone and high brightness. Now the ambient light is rather obvious, it should be used for all objects, as well as the directional light, but the other two confuse me: While the point light might light a bigger part of the object, the narrow cone of the spot light might be more noticable, especially if it is neglected for some frames and then pops back in. I admit the example is a bit invalid because four light sources won´t be a problem anyway, so just assume there are many more lights that could affect the object. So, how could an algorithm look like that determines which lights should actually be used?

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Why would you have 30 discreet lights affecting any single object? And don't count "ambient" as that's basically a freebie in your lighting shaders.

I'm no quite an expert on shaders, but my understanding is that you can have as many lights as you can pack into the available variables, right? That seems like a decent number of lights.

FYI, the Splash Damage guys said that in Enemy Territory: Quake Wars, they average *fewer* lights than in Doom3/Quake4.

The C4 engine does something interesting; at the load-time for a scene, it calculates all the possible light/surface combinations and creates a unique shader for each. This isn't really all *that* difficult to accomplish and as long as you have nicely discreet "shader blocks" you can easily add new lighting and surfacing techniques.

Share this post


Link to post
Share on other sites
seems like a misunderstanding.
The problem currently is not how to actually render an object with an "arbitrary" number of lights, the problem is how to find out which of these 30 lights would have the most impact on the object´s look and to use these for rendering later on.

Share this post


Link to post
Share on other sites
"The lights that influence the object the most"

In reality, only the lights that contribute to the modification of color of a given pixel on the screen really matter.

As the post before mentions, there's a number of ways to factor this in:

Distance : lights further from an object will have less visual effect on an object as your view point gets farther from it. Some titles do this with shadows as well, IE you 'fade' out shadows and lights as you get further from them.

Intensity : If an object falls within the near attenuation, the intensity of contribution of the light on the object is greater than if it falls into the far attenuation or at lower percentages of the decay distance.

Chrominance : If two lights are equal in distance and intensity, the color contribution difference between the two lights can make up for a large portion of visual influence.

Maxout : If the pixel contribution of a light is that which it maxes out the value of a pixel, then this light's value is un-needed. (Note, this is for scenes that don't have HDR or emissive elements for bloom etc)

There's a ton of other pieces of data that could factor into the situation depending on your game type and lighting type.

~Main

Share this post


Link to post
Share on other sites
okay, so this is just about finding a suitable "weight function" for some of these parameters like distance light <-> object, luminance and color contribution (and/or other factors that could affect visual appearance if necessary)? I guess it is usually enough to sample that weight function for the center of the object, if the object doesn´t get too big, and perhaps for the vertices of a simpler bounding volume if the object gets bigger?
After that is done I should be able to sort the lights for "importance" to the current object and simply pick the most important ones I guess.
How many lights are realistic to do in one pass nowadays without shadows and with shadow-mapping? I´m using HLSL and intend to support Shader Model 2.0 hardware or better.

Share this post


Link to post
Share on other sites
I'm doing about 20-30 additive (non shadowcasting) lights on a single object at one time.

Once you throw shadows in there though, things get exponentially more expensive to render.

~Main

Share this post


Link to post
Share on other sites
Yeah that could get expensive in a forward renderer - no two ways about it. In particular, the computation overhead for finding and sorting suitable lights is nontrivial in a fully dynamic scene.

My by suggestion is to use your bounding volume hierarchy as best you can to get a short list of lights that may affect your object, then sort them by importance (probably a function of distance, priority, intensity, etc). One simple metric would be to compute the light intensity at the nearest point on the BVH, or even the center point.

It's going to be tough to avoid "popping" if you don't use all of the lights though, and anything is in motion. Probably the best solution involves always doing all of the lights that could potentially affect an object, and then getting the level/lighting designer to avoid putting too many lights with overlapping bounding volumes.

If you're not doing HDR, you can probably get away with only doing the few "most intense" ones, hoping that it will push it over 1.0 (and thus get clamped). With HDR you most certainly cannot do this. It also won't work for several less-intense lights.

Anyways there's not really a good solution that I've found. That's just the price that you pay for trying to reduce the geometric complexity of lighting in a forward renderer.

Share this post


Link to post
Share on other sites
@ElFrogo:
20 to 30 lights without shadows? Sounds like it would be enough.

@AndyTX:
Yes, using the BVH (in my case a simple QuadTree) to cut down the number of lights I have to check more precisely was one of the things I was thinking about. I´m not going to implement HDR but I don´t want to be left hoping that the lighting will reach 1.0 before I "run out of lights" ;)

Perhaps it might work to do the following:
If it is really possible to do 20 to 30 lights in one pass without shadows I should be able to get _all_ lights affecting one object into one pass (I hope I won´t reach 10 lights for one object).
If I can do all lights without shadows in one pass, I should be able to pick the 2 or 3 lights that have the most impact on the whole screen and render them using shadows, right? I guess if I do it right I should be able to use 2 or 3 shadowmaps in one pass (if they´re filled beforehand of course).

So all in all the plan is:
1. Do frustum culling on the scene´s objects, leaving me with visible objects and a bounding volume that contains all visible objects.

2. Do an intersection test with all lights and the visible objects´ bounding volume. If a light intersects the visible part of the scene add it to the list of potential light sources for the current frame.

3. Based on light intensity, distance from the visible scene, perhaps volume of the intersection with the visible scene and things like that choose the 2 to 4 most important lights to the scene and fill shadowmaps for them.

4. Assemble a list of lights for each object containing the lights that affect the object at all. This list will be a subset of the lights surviving step 2.

5. Render every object using the corresponding lights from step 4.

Does this plan sound feasible?

Share this post


Link to post
Share on other sites
u need to less all lights contribute to it (if there intensities are say greater than 0.01, lightstength vs distance )
i used to cap the number of lights that would affect the object at 8or12 (i forget), thinking yeah well the thirtheenth light is not gonna be seen amongst the other 12 brighter ones but in fact visually u can notice it, the eye is very receptive to changes in brightness.

Share this post


Link to post
Share on other sites
20-30 lights is probably only reasonable if you're not doing specular on all of them, and perhaps not even attenuation (although the latter is really required to bound the light extents and prevent popping). That simiplifies the math to a few arithmetic instructions and the dot(N, L). This would be reasonable to do for 20-30 lights on modern hardware.

Again, you'll probably have to choose which lights get the specular treatment (which is a bit odd, considering the physics of all of this), but the pow() is expensive.

Share this post


Link to post
Share on other sites
So in fact some kind of light "LOD" scheme would be feasible?
If I have a weight function that expresses this abstractum "importance" of a light in a range from 0 to 1, I could take the 3 most important for the whole scene and do shadowmaps for them. So these 3 are going to get the most detail (diffuse lighting, attenuation, specular and shadows). Then every remaining light that lies in 0.75 to 1 (or something similar, I guess that would need some tweaking and of course knowledge of the used weight function) would get rendered with diffuse lighting with attenuation and specular and the remaining light just with diffuse lighting and attenuation. Taking attenuation out for a light doesn´t seem to be an option, since that would cause the light to suddenly seem brighter at far away objects, as AndyTX mentioned.
As I have said I hope there won´t be more than 10 lights affecting one object, so with the very crude scheme above I think I should have 3 lights with shadowmapping, specular and diffuse lighting, about 2 or 3 more lights with diffuse and specular lighting and 4 or 5 lights with just diffuse lighting max.

However I was thinking whether it was possible to "fake" the lighting caused by the more unimportant lights with just an ambient light representing the overall brightness and color of the faked lights. Of course that would be a very rough approximation, but perhaps it works for taking out the 3 or 4 lights that would only contribute very little to the object´s appearance anyway.

Share this post


Link to post
Share on other sites

20-30 lights per-pixel would be expensive on almost any rendering method (deferred or forward) at the moment. I don't want to get into a deferred/forward debate in this thread though, we can do that elsewhere :) So just remember that you can do multiple lights per pass (its not that hard). Deferred will scale better for more lights, no doubt.

One alternative is to do full lighting calcs on the closest N lights, and for TOTAL-N just approximate them with a few "fake" lights that are averages of their light dir/intensity etc. If you need shadowing, your out of luck doing that, but your probably in trouble anyways. This method is used in quite a few pc/ps2 games. We used to do 2-3 main lights plus ambient, then approximate the rest with one light. You could probably just segment the remaining lights around the object using a simple split (quad, octree), and put a light in each segment which represents the remainers. Don't have to be crazy accurate here as they are approximations, but you will probably want to either skip specular, or make its contribution minor.
There are many other ways to do this same thing (its in a similiar vein to using Irrad Volumes and SH lighting), but you could probably get away with less.

Share this post


Link to post
Share on other sites
Yeah as multisample mentioned there are potentially ways to "combine" lights (approximation of course) that could be useful. In particular, I remember a paper about "light cuts" that would represent all of the lights in a scene as a tree, and choose a "cut" through the tree (effectively a level in each subtree) that would minimize the error.

In any LOD scheme you're going to have some troubles with popping. In particular popping in and out of shadow mapped to non-shadow mapped is probably not a good idea. That could potentially have entire shadow silhouettes flickering, which is going to be *very* noticable.

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Yeah as multisample mentioned there are potentially ways to "combine" lights (approximation of course) that could be useful. In particular, I remember a paper about "light cuts" that would represent all of the lights in a scene as a tree, and choose a "cut" through the tree (effectively a level in each subtree) that would minimize the error.

I´d definitely be interested in reading that paper. Do you think you might find it again? ;)

Quote:
Original post by AndyTX
In any LOD scheme you're going to have some troubles with popping. In particular popping in and out of shadow mapped to non-shadow mapped is probably not a good idea. That could potentially have entire shadow silhouettes flickering, which is going to be *very* noticable.

I agree on the popping issue and I wonder how other games take care of that? I don´t think it is uncommon to have too many lights in a complete map to have them all cast shadows.
One thing I´ve been thinking about was to divide the shadowmap updates over different frames. Assuming the application is running at ~60 FPS, it should suffice to update every shadowmap every 3rd frame, which would be around ~20FPS. I think that should be enough and would allow to triple the number of shadowcasting lights, except if the shadowmap lookups consume too much time.
However that still doesn´t solve the popping issue, it just "delays" it until more lights appear on screen.

Share this post


Link to post
Share on other sites
Quote:
Original post by matches81
I´d definitely be interested in reading that paper. Do you think you might find it again? ;)

I think it's this one, but I'm not at school right now so I can't be sure...

Quote:
Original post by matches81
One thing I´ve been thinking about was to divide the shadowmap updates over different frames.

That's a fairly common way of avoiding the computation cost every frame (the same can be done for environment maps, etc). If you have the memory to spare, certainly try it out.

[Aside: This sort of thing actually doesn't play well with SLI and similar technologies since it introduces a dependency between GPUs if they are performing alternate-frame-rendering... probably not a bit issue for you, but I figured I should mention it anyways.]

Share this post


Link to post
Share on other sites
Quote:
Original post by AndyTX
Quote:
Original post by matches81
I´d definitely be interested in reading that paper. Do you think you might find it again? ;)

I think it's this one, but I'm not at school right now so I can't be sure...

Too bad. Can´t get that article, since I´m not from the USA and credit cards aren´t that widespread here :(
Thx anyway for digging it out, I managed to at least find another pdf mentioning lightcuts and "explaining" them (though without explaining variables in some equations :( ) and I´ll search a bit more for those things ;)
[edit]
found a copy of the article, will read it now and see if I grasp it ;)
[/edit]

Quote:
Original post by AndyTX
Quote:
Original post by matches81
One thing I´ve been thinking about was to divide the shadowmap updates over different frames.

That's a fairly common way of avoiding the computation cost every frame (the same can be done for environment maps, etc). If you have the memory to spare, certainly try it out.

[Aside: This sort of thing actually doesn't play well with SLI and similar technologies since it introduces a dependency between GPUs if they are performing alternate-frame-rendering... probably not a bit issue for you, but I figured I should mention it anyways.]


Ack... while currently SLI is not a big issue for me it might become one soon enough. I suppose the problem is that the shadowmaps one GPU updated reside only in the video memory accessible by that GPU and would have to be copied over to the video memory for the other GPU to use, right?
Is there any way to to distribute shadowmap updates and do it "SLI-friendly"?

Share this post


Link to post
Share on other sites
another way to try and avoid the flickering might be to include the "fitness" of the lights over the last N frames in your fitness function, but im not sure how well this would work or if it did work it may add to much overhead so...

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Lightcuts: a scalable approach to illumination

http://www.cs.cornell.edu/~kb/projects/lightcuts/

Share this post


Link to post
Share on other sites
Quote:
Original post by matches81
Is there any way to to distribute shadowmap updates and do it "SLI-friendly"?

For alternate frame rendering SLI? I suspect that anything other than re-rendering the whole frame will incur a synchronization cost (and probably a fairly hefty one). Note that there probably won't be a problem with this approach if using a different SLI mode like split-frame rendering, but you may not get as good scaling.

As an aside, all of this SLI info is in the NVIDIA GeForce Programming Guide, in case you feel like browsing through that.

Share this post


Link to post
Share on other sites
Thx for the tip with the nVidia SLI guide, will look through it some time.

Let´s see if I understand that lightcut stuff correctly:
First you build a global light tree, which is an ordinary binary tree with the original lights as leaf nodes and every other node being a possible replacement for its children. After that, I have to choose which nodes (lights) of the tree to use for a specific part of the picture, which is the lightcut.
If this is correct, I think the only problem would be that I would need to calculate an error criterion. In the paper the lightcut technique seems to pay off only for a magnitude of light sources that I hope I´ll never reach. However I think that this is because they choose a quite small error threshold, right?
If I allow a higher error to occur the lightcut should be effective for a smaller number of lights.

Now, assuming I have an error criterion algorithm set up, I should be able to build that light tree, choose a lightcut for every quadtree node and store it there (I guess this should be doable when loading a map, shouldn´t take that long I assume).
After that every object in that quadtree node should be rendered using that lightcut. The only problem with this are objects that lie in two or more quadtree nodes. However, since the lightcuts of neighboring quadtree nodes ought to be similar it should be possible to determine a "tradeoff" lightcut which is good enough for both most of the time.
Perhaps using three different lightcuts (for the three light LOD "groups") would be feasible. However that would make the case of an object lying in two or more quadtree nodes even more ugly, having to get that "tradeoff lightcut" three times.

Somehow I get the feeling that I´m again doing too much in theory without implementing and trying it ;)

Share this post


Link to post
Share on other sites
Quote:
Original post by matches81
Somehow I get the feeling that I´m again doing too much in theory without implementing and trying it ;)

Theory is good though, as is design... sucks to have to rewrite wads of code. If I could do only theory and have the computer "just understand", I'd be a happy person :)

It seems that you have the idea of light cuts... I'm not totally sure that the paper used it in real time, so perhaps something similar with a courser approximation is in order. There are probably optimizations to be made with fewer sets of lights as well. In any case I'd be interested in seeing/hearing about your results!

Share this post


Link to post
Share on other sites
Quote:
Original post by jamesw
Quote:
you cant devide shadow computation over serveral frames


Could you tell about that more? What was the problem?

its one of those ideas that seem good in theory + then u try it and its yuck
the problem is say u have a person walking through the light area, if u dont update each visual frame u can easily tell that the shadow on the ground is not in sync with the shadow caster, it looks terrible, not to mention selfshadowing is totally screwed up as well, as the polygon depth comparrision of camera scene vs light scene aint equal

Share this post


Link to post
Share on other sites

This topic is 4094 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this