56 lines
2.2 KiB
C
56 lines
2.2 KiB
C
void lambert() {
|
|
#if LIGHTING_IN_WORLD_SPACE
|
|
const vec3 POSITION = surface.position.world;
|
|
const vec3 NORMAL = surface.normal.world;
|
|
#else
|
|
const vec3 POSITION = surface.position.eye;
|
|
const vec3 NORMAL = surface.normal.eye;
|
|
#endif
|
|
|
|
// outcoming light from surface to eye
|
|
const vec3 Lo = normalize( -POSITION );
|
|
|
|
for ( uint i = 0, shadows = 0; i < MAX_LIGHTS; ++i ) {
|
|
#if BAKING
|
|
// skip if surface is a dynamic light, we aren't baking dynamic lights
|
|
if ( lights[i].type < 0 ) continue;
|
|
// shouldn't ever need this, but in the event we hit the end of the buffer and everything after is corrupted
|
|
if ( lights[i].type <= 0 ) break;
|
|
#else
|
|
// skip if surface is already baked, and this isn't a dynamic light
|
|
if ( surface.material.lightmapped && lights[i].type >= 0 ) continue;
|
|
#endif
|
|
// incoming light to surface (non-const to normalize it later)
|
|
#if LIGHTING_IN_WORLD_SPACE
|
|
vec3 Li = lights[i].position - POSITION;
|
|
#else
|
|
vec3 Li = vec3(VIEW_MATRIX * vec4(lights[i].position, 1)) - POSITION;
|
|
#endif
|
|
// magnitude of incoming light vector (for inverse-square attenuation)
|
|
const float Lmagnitude = dot(Li, Li);
|
|
// distance incoming light travels (reuse from above)
|
|
const float Ldistance = sqrt(Lmagnitude);
|
|
// "free" normalization, since we need to compute the above values anyways
|
|
Li = Li / Ldistance;
|
|
// attenuation factor
|
|
const float Lattenuation = 1.0 / (1 + Lmagnitude);
|
|
// skip if attenuation factor is too low
|
|
// if ( Lattenuation <= LIGHT_POWER_CUTOFF ) continue;
|
|
// ray cast if our surface is occluded from the light
|
|
const float Lshadow = shadowFactor( lights[i], 0.0 );
|
|
// skip if our shadow factor is too low
|
|
// if ( Lshadow <= LIGHT_POWER_CUTOFF ) continue; // in case of any divergence
|
|
// light radiance
|
|
const vec3 Lr = lights[i].color.rgb * lights[i].power * Lattenuation * Lshadow;
|
|
// skip if our radiance is too low
|
|
// if ( Lr <= LIGHT_POWER_CUTOFF ) continue;
|
|
// angle of incoming light
|
|
const float cosLi = DOT(NORMAL, Li);
|
|
|
|
const vec3 diffuse = surface.material.albedo.rgb;
|
|
const vec3 specular = vec3(0);
|
|
|
|
surface.light.rgb += (diffuse + specular) * Lr * cosLi;
|
|
surface.light.a += lights[i].power * Lattenuation * Lshadow;
|
|
}
|
|
} |