Rendering with only 8 lights active

Started by
11 comments, last by Krohm 10 years, 4 months ago

Scenario:

you have a scene with 1000 lights,but you can only have 8 active at a time.

How do you go about rendering your meshes in a performance wise mode?

Advertisement

You'll have to select the 8 most important lights for each draw call you make. There are a lot of ways to do this. One way is to create an oct-tree or some other kind of spatial data structure that can store all your lights. A light is stored inside an oct-tree node when that light's volume intersects the node's volume. Then, when you wish to draw a surface, you will iterate through each light stored inside each oct-tree node that your surface's volume intersects. If a light volume and the surface volume intersect, then you keep track of that light. Once you've tested all the relevant lights, if you have 8 or fewer lights that intersect your surface's volume, you can select those lights and render. If you have more than 8 lights, you'll have to do some more computation to see which lights are the most important (brightest, closest, whatever) and select those 8 lights.

Hi, (I'm no Dx9 expert, so I'm not sure whether this is even possible)

Samith has a good point. And if your target is performance, I'd recommend to follow his method. But if you really want to render more than 8 lights:

Store your lights in your own structure, saving them somewhere. Then when rendering your mesh, do the following: (Not checked for bugs)


.. 
// Split all your lights in the scene up to arrays* with 8 elements in each
// Make sure that at least one element is returned, even though that is has
// 0 lights, making sure that the mesh is drawn
std::vector<std::vector<LightType>> lights;
SplitLights(&lights, 8);

// lights could look like this::
// Element: ( max 8 )
//     LightA
//     LightB 
//     LightC
// Element: (max 8, ideally these lights should be in element 0, but you get the idea...)
//     LightD
//     LightE 
//     LightF

// Render the mesh without any lights
RenderMesh();

EnableAdditiveBlending();

for( int i = 0; i < lights.size(); i++)
{
    until(lights[i].size()) SetDXLight(light[i]);

    // Render the mesh with ONLY the lights
    RenderMesh();
}

This might not be the best nor fastest, but it should work and provide you your results.

EDIT: You might need to enable some kind of additive blending.

Hope this helps.

-MIGI0027

FastCall22: "I want to make the distinction that my laptop is a whore-box that connects to different network"

Blog about... stuff (GDNet, WordPress): www.gamedev.net/blog/1882-the-cuboid-zone/, cuboidzone.wordpress.com/

From the lights that the camera can see in the current frame, pick the 8 closest to the camera.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Wouldn't that look bad if you have 8 lights near the camera and some objects together with more lights that you ignore and outside the range of those 8 lights?

Yep, but if you have to specify a limit on the lights you can draw, well, if you have more lights in the viewable scene that you can draw, it will look bad regardless of what you do. Light popping in/out of existence.

The best you can do is to select which lights you're going to draw as best as possible (ie, the ones that will have most impact in the scene).

That's why when an engine has a hard limit on the amount of lights of certain types, level designers do their best to make scenes that work and look good under those limits.

Say for example, the limit on shadow casting lights for Skyrim is 4. Go over that and the lights fck up. Thus no single interior cell* in the entire game (a game which has hundreds of hand crafted interior cells) has more than 4 shadow casting lights.

* I don't remember exactly if the limit was per interior cell or just by room/bounding volume + whatever room you see through the portals.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

One of the keys to this is to not make huge meshes, so in practice up to 8 lights lighting one mesh is more then enough. In practice I found out that even 4 is reasonably ok (for bw compatibility if you need it, performance wise).

This is what I do:
- cull all positional lights against frustum
- for each renderable/ mesh store the 8 closest lights that effect the mesh
(simple boundingsphere vs boundingsphere radius check)
- send only these lights to the shader

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Personally, if I'd have a realistic test case in which I need to have more than 100x the amount of supported lights, I'd start considering other methodologies, such as deferred shading.

Previously "Krohm"

Personally, if I'd have a realistic test case in which I need to have more than 100x the amount of supported lights, I'd start considering other methodologies, such as deferred shading.

This.

Unless there is a specific reason you want to do forward rendering with 1000 lights, I would do some research in deferred shading and perhaps use that.

It also depends a bit on how the lights are spread through the scene though, although some kind of spatial data structure is recommended regardless. If you're going to have a high density of lights within your view, it's very likely never going to be looking good regardless of how you do it (with forward rendering), unless you give up performance for some fancy alghorithm which I am not sure if it would be feasible if it exists.

If it's going to be something along the line of a city, at least where most of the lights are occluded by something, you should certainly have some kind of spatial data structure and probably checks if the light is even worth using (fully occluded by a wall you're standing next to for example).

Deferred shading is the way to go with so many lights, but artistically speaking there are too many lights in there. There are different "kind" of lights you want in a scene:

1. lights you want to see (i.e. light bulbs). You can use some halo textures and light maps to bake these in, having little performance impact

2. lights that you want to see reflected, like if you have a car in a show room and you want lots of lights bouncing off its surface, you usually solve this using some environment texture mapping effect

3. light that actually affect stuff which can be also per-vertex or per-pixel, the later being the real performance hogs.

From an artistic point of view however the less lights you use, the less confusing is for the player and the more dramatic effects you can obtain. If you look at professional films and photos you can see there are only a few lights that are used in a clever way to produce astounding effects. The more lights you add, the more fatigue and confused the player will get.

This topic is closed to new replies.

Advertisement