N dot L vs. (N dot L) * .5 + .5

Per Enrico’s suggestion: It seems to just add an emissive light of .5 for each light?

Per Enrico’s suggestion:

N.L vs N.L *.5 + .5

It seems to just add an emissive light of .5 for each light?

7 replies on “N dot L vs. (N dot L) * .5 + .5”

Not really.

Standard diffuse – saturate(N dot L) – is completely black on the backside.

With ambient and lowered light intensity that would be 0.5 + 0.5 * saturate(N dot L) – so that would be 50% gray on the backside, and would go from 50% gray to white on the front side.

0.5 + 0.5 * (N dot L) is called “wrapped diffuse”; it does no saturation but just scales the dot from -1..1 range into 0..1 range. So it goes from black to white over the whole range and generally looks nicer than 50% lighting with 50% ambient. That is, the backfaces don’t look “flat”.

The lower sphere looks much, much better in my opinion 🙂
Do you like the appearance of the lower sphere? 🙂

Both BRDFs I posted try to simulate Indirect Lighting: Light bounces off of surfaces in the real world, so not only the part where a light points at gets illuminated, but although all points around it (to keep it very short 😀 ). But I think you already know that. Indirect lighting is usually simulated with an ambient term, while the emissive term is used to simulate objects which glow itself. The difference between Half Lambert and Wrap Lighting and emissive/ambient term is the geometry-dependency. This looks much, much better than just emissive and ambient term, especially when using ambient occlusion or PRT or similar stuff. Do you have Ambient Occlusion or PRT information added to your models and environment?

Personally I prefer the Wrap Lighting, as the appearance can be changed at runtime 🙂 Ah, and the formula I posted for this can be optimised a little, but I wanted to keep it short and self-explanatory 😉

The second looks better because it is lit. Maybe I misunderstood you?

This is what I had before:
float4 decalColourNL0 = decalColour * max(0.0f, dot(normal, IN.tsLightDir0))*lightDiffuse0;

This is with the change you suggested
float4 decalColourNL0 = decalColour * max(0.0f, dot(normal, IN.tsLightDir0)*.5 + .5)*lightDiffuse0;

No time or money for Ambient Occlusion or PRT. Some of that has to be exported with the model and I am using oFusion which is a problematic exporter that doesn’t let me extend it.

Your version is not completely correct, you are missing the multiplication and you can optimise the max()-function out. This results in:

This is with the change you suggested
float HalfLambert = dot(normal, IN.tsLightDir0) *.5 + .5;
float4 decalColourNL0 = decalColour * HalfLambert * HalfLambert * lightDiffuse0;

Ops, ignore this line “This is with the change you suggested” 😉

Its sad, that you can’t include at least Ambient Occlusion (for now, maybe?). It is really worth it 🙂

Since you’re using max you can easily add ambient occlusion to the vertex colours. Add a sunlight and render->advanced lighting->radiosity, set the detail up a bit and render. There’s a plugin which will bake the rendered light into the vert colours. I’ll ask my artist

Leave a Reply

Your email address will not be published. Required fields are marked *