draw lights in render engine

Started by
2 comments, last by 21st Century Moose 7 years, 10 months ago

I 'm going to write the lighting for game. I have read many code, and finally conclude two way to draw light models.

1)

foreach(model in models)
{

model.draw(model.material, model.HitLights); // the hit lights are pick up by collision test.

// if no hit lights, it will be drawed with ambient.

}

To implement this method , it seems to precompile many technique, material + 1 light, material + 2 lights ....

2)

the so called forward lighting ????

drawall(models, ambient light);

foreach(light in lightlist)

{

find hit models;

bindpass(lightingpass);

foreach(model in hits)

draw(model, light);

}

this method look more simple, because I only need to write one shader file.

If not considering efficiency, the second one may look better. For the moment, I don't want to use deferred lighting technique.

How do you do forward lighting ?

In the second method, how to real time combine other shader into the main lighting shader ?

For instance, the main lighting shader code in the file lighting.shader. And a shader file aa.shader which has a function computeColor().

How to real time combine the code from aa.shader into the lightin.shader.

so the main() in lighting.shader can call the computeColor() ?

hehe, i'm now using dx11

Advertisement
Those are both different implementations of forward lighting. (1) Is single pass forward lighting and (2) is multi-pass forward lighting.
(2) Used to be popular back before shaders, or with the early shader models.
(1) Replaced it when shaders became flexibly enough.

They should both produce the same visual result -- except if you're not doing HDR (e.g. are using an 8-bit back buffer). In that situation, (2) will have an implicit saturate(result) at the end of every light, whereas (1) will only have this implicit clamp right at the end of the lighting loop.

There's also a middle-ground that prevents a technique explosion -- stop at material + N lights, and use
foreach(model in models) 
{ 
  for( i = 0; i < model.HitLights; i += N )
    model.draw(model.material,  model.HitLights.SubRange(i, i+N) );
}
Or another alternative -- you used to pre-compile many shader permutations (material + 1 light, material + 2 lights ...) because using a dynamic loop inside a shader used to be extremely slow.
These days, loops are pretty damn cheap though, so you can just put the number of a lights (and an array of light data) into a cbuffer and use a single shader technique for any number of lights in one pass.

They should both produce the same visual result -- except if you're not doing HDR (e.g. are using an 8-bit back buffer). In that situation, (2) will have an implicit saturate(result) at the end of every light, whereas (1) will only have this implicit clamp right at the end of the lighting loop.

Can you explain it ?

What you're not mentioning is how (if at all) you're planning to implement shadows. Method 2 will integrate more cleanly with typical shadowing techniques, especially if you want to have an arbitrary number of shadow-casting lights.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement