Advertisement

Multiple lights and/or lighting models.

Started by November 10, 2014 01:12 PM
9 comments, last by cozzie 10 years, 2 months ago

hi.

i just covered a chapter on point lights from braynzarsoft - 16.1 point lights. unfortunately there was no hints or instructions on hwo to do multiple lights, or perhaps even have different models alltogether.

i have wild guesses that are likely slow as fu**.

can anyone please tell me how can you have multiple point lights at the same time?

http://en.wikipedia.org/wiki/Phong_reflection_model

Convert the formula into code:


//pseudo-code:
//intensity is a 3d vector (r,g,b)
//AmbientLight is a 3d vector (r,g,b) - one ambientlight per scene! - not per light
float3 Intensity = AmbientLight*material.diffuse
float3 pixel_to_light = 0;
float3 pixel_to_eye = camera.pos - pixel.pos;
float3 pixel_to_light_reflected_by_normal = 0;
float distance = 0;
for(int i = 0; i<lightsCount; i++)
{
    pixel_to_light = light[i].pos-pixel.pos;
    distance = length(pixel_to_light);
    pixel_to_light /= distance;
    if(distance > light[i].radius)
        //skip
    pixel_to_light_reflected_by_normal = 2*dot(pixel.normal, pixel_to_light)*pixel.normal - pixel_to_light;
    Intensity += (light[i].diffuse*material.diffuse*max(0,dot(pixel_to_light,pixel.normal)) + light[i].specular*material.specular*max(0,dot(pixel_to_eye,pixel_to_light_reflected_by_normal))^material.shininess)/(light.att[0] + light.att[1]*distance + light.att[2]*distance*distance)
}

Should look something like this.

If you've got textures, separate the different terms(ambient,diffuse and specular) in different variables and you should have something like this:


finalColor = saturate(textureColor*(ambient+diffuse) + specular);

If you read the theory on the wiki page it should become more than obvious.

Advertisement

http://en.wikipedia.org/wiki/Phong_reflection_model

Convert the formula into code:


...

i haven't covered or have any idea of specular or reflection. i'm guessing what you did want to show is that it is a simple for loop processing each light from a constant buffer(the entire array of lights is sent when even one light changes)?


i have wild guesses that are likely slow as fu**.

Depends greatly how you implement them - forward rendering and multiple light sources is totally possible and is used in many many games - of course the amount of light sources was a bit limited - although using clever tricks could give impression of lots of light per object.

Keep in mind that with forward rendering you'll need to do some serious light culling - you can't loop ALL the lights in the world for each pixel. Instead you'll need to choose (based on distance and intensity) which lights affect which object. For example, Half-Life 2 used max 2 dynamic light sources per object.

Deferred rendering will increase the amount of lights affecting each object and will improve batching since the lighting is done in the screen space - the disadvantage typically is that you are limited to one (or few) lighting models. The amount of visible lights per frame may be in hundreds without big performance hit (of course depends on the lighting model and no shadow maps used).

There is also Forward+ technique which I'm not too familiar about but it tries to combine the advantages of deferred shading (lots of light sources) and forward rendering (multiple lighting models).

Cheers!

Keep in mind that with forward rendering you'll need to do some serious light culling - you can't loop ALL the lights in the world for each pixel. Instead you'll need to choose (based on distance and intensity) which lights affect which object. For example, Half-Life 2 used max 2 dynamic light sources per object.


so you choose closest lights in a scene based on distance from the object? if so, sounds like thish is exactly that 'lots of trickery'.

Deferred rendering will increase the amount of lights affecting each object and will improve batching since the lighting is done in the screen space - the disadvantage typically is that you are limited to one (or few) lighting models. The amount of visible lights per frame may be in hundreds without big performance hit (of course depends on the lighting model and no shadow maps used).

There is also Forward+ technique which I'm not too familiar about but it tries to combine the advantages of deferred shading (lots of light sources) and forward rendering (multiple lighting models).


i don't understand half of what you'r saying smi148.png

deferred rendering, batching, light culling, shadow maps, forward rendering... i'm just a little banana trying to learn form a tutorial.


so you choose closest lights in a scene based on distance from the object? if so, sounds like thish is exactly that 'lots of trickery'.

Well, this is the least that you'll need to do in the case you have lots of lights in your world - it isn't really trickery, just a question of optimization because we still don't have infinitely fast computers.

If you are experimenting with a simple scene and you have few lights then these kinds of optimizations aren't necessary - just loop through all the lights as pointed out by Lightxbulb and it won't be slow as h*ll.

Lighting is one of the hardest parts in a graphics engine. I'm just trying to point out that in order to scale the number of lights you'll need to use pretty different ways of drawing the scene - of course, the lighting formulas stay the same.

Cheers!

Advertisement

Btw you can remove the specular term, if you don't get how it works yet(http://en.wikipedia.org/wiki/Specular_highlight) - though I'd advise you implement it right away if you get the theory. For multiple lights it's done with a loop - when you have a sum (the sigma in the Phong illumination model) you use a loop. What happens is basically each light contribution is calculated then added together. Mind you the pseudo code I wrote was for point lights, directional lights don't have position. What kauna is mentioning is a little higher level - when you get to optimization and you start having concerns about how fast your code runs. I'd advise you check out this book: http://prelight.googlecode.com/files/Programming%20Vertex%20Geometry%20and%20Pixel%20Shaders.pdf and I'd recommend Frank Luna's book. You can check out Blinn Phong while you're at it - the only difference is how the reflected vector is calculated for the specular term.


deferred rendering, batching, light culling, shadow maps, forward rendering... i'm just a little banana trying to learn form a tutorial.

Light culling : determination of which lights affect which objects, or determining if the light is visible on screen

Batching : drawing multiple objects with a single draw call. D3D API has a big overhead for draw calls - for that reason drawing multiple objects with one draw call is a good option.

Shadow maps : typically a depth texture rendered from the point of the view of a light source (directional or spot) - when combined with lighting calculations, it is pretty efficient to find out which pixels shadowed. Can be used with forward or deferred renderer.

forward rendering : the lighting is accumulated when rendering primitives (as shown in the previous posts). Disadvantages : batching is difficult (but not impossible) since you'll need to know which lights affect which object at the moment when you draw the object.

deferred rendering : instead of calculating the lighting contribution for each pixel, you'll store the information required for the lighting calculations in textures. The information consists typically of pixel position, surface normal, albedo, specular factor, roughness.

After writing all the geometry data, you perform a lighting pass and read the data from the textures to calculate the lighting for each pixel. Since the lighting is processed in the screen space it is easy to find out which lights affect which pixels. This means that the lighting calculations are deferred -> performed later. Advantages : batching is easy since drawing objects and lighting are separated - no need to know about lights when drawing the objects. Disadvantages : memory/bandwidth consumption for the textures storing and reading the geometry data.

Forward and deferred rendering have their advantages and disadvantages (I didn't write all of them here) so it isn't this easy to make a choice between them.

Cheers!

Checking if a light affects an object based on radius versus bounding sphere doesn't sound tricky at all if you ask me. It's just an effective form of early culling and saving unneccessary light calculations.

You also might wanna check out this topic:
http://www.gamedev.net/topic/657701-most-efficient-way-for-lighting-in-forward-rendering/

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

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


i'm just a little banana trying to learn form a tutorial.


Learning the underlying concept of lighting as it relates to computer graphics, and all the other terms that others have mentioned I find will get you more in the long run than just looking at a tutorial. The tutorial just applies the concept, so no matter how much you look at the tutorial or copy and paste the code, you will never figure out whats going on unless you at least understand the basics. For example, in regards to your original question, using multiple lights is just an extension of using a single light(s) accumulated effect is added. Thus, a loop over all the relevant lights is what you are looking for and I think you already referred to that. As for efficiency, that is another question, and others have already mentioned ways to help in that aspect..

This topic is closed to new replies.

Advertisement