accumulateLights function
Vector3
accumulateLights(
- Surface s,
- ShaderBindings b,
- FragmentContext c, {
- required Vector3 shade(
- Surface s,
- LightSample light
- required bool shadowed,
AccumulateLights, with the model's own response passed in.
The GLSL achieves this with two function prototypes each shader defines; here it is a callback, which is the same shape and one fewer file.
Implementation
Vector3 accumulateLights(
Surface s,
ShaderBindings b,
FragmentContext c, {
required Vector3 Function(Surface s, LightSample light) shade,
required bool shadowed,
}) {
var total = Vector3.zero();
final count = lightCount(b, s.world);
for (var i = 0; i < count; i++) {
final light = sampleLight(b, i, s);
if (light == null) continue;
// `LightHasShadow` — `gfx-74n`. Only the first eight carry one: the atlas
// has six rows and the slot table eight entries, so a light from the list
// has no row to read and asking would index past the table.
var visibility = 1.0;
shadowTransmittance.setValues(1.0, 1.0, 1.0);
if (i < kMaxLights) {
visibility = shadowed ? shadowFactor(s, b, i, light.nDotL, c) : 1.0;
visibility *= pointShadowFactor(b, s.world, s.normal, i, c);
}
if (visibility <= 0.0) continue;
final response = shade(s, light);
total += Vector3(
response.x * light.radiance.x * shadowTransmittance.x,
response.y * light.radiance.y * shadowTransmittance.y,
response.z * light.radiance.z * shadowTransmittance.z,
)..scale(light.nDotL * visibility);
}
return total;
}