contributorLight function
({Vector3 radiance, Vector3 toLight})
contributorLight(
- ShaderBindings bindings,
- int index,
- Vector3 world
ContributorLight — N6: light index as world receives it, with no
surface to face. A rectangle is read as a point at its centre, as the GLSL
reads it.
Implementation
({Vector3 toLight, Vector3 radiance}) contributorLight(
ShaderBindings bindings,
int index,
Vector3 world,
) {
const block = 'ContributorLightInfo';
final fromList = index >= kMaxLights;
final slot = index - kMaxLights;
final fromCell = fromList && clustered(bindings);
final row = !fromList
? -1
: fromCell
? clusterRow(bindings, world, slot)
: lightListRow(bindings, slot).round();
Vector4 read(String member, int column) => fromList
? lightListTexel(bindings, row, column)
: bindings.vec4(block, member, Vector4.zero(), at: index);
final position = read('light_position', 0);
final color = read('light_color', 1);
if (fromList) {
color.w *= fromCell
? (inSlots(bindings, row) ? 0.0 : 1.0)
: lightListScale(bindings, slot);
}
final direction = read('light_direction', 2);
final cone = read('light_cone', 3);
final type = position.w;
final directional = type < 0.5;
final offset = Vector3(position.x, position.y, position.z) - world;
final distance = offset.length;
final aim = Vector3(direction.x, direction.y, direction.z);
final aimLength = aim.length;
if (aimLength > 0.0) aim.scale(1.0 / aimLength);
final degenerate = !directional && distance < 1e-6;
final toLight = directional
? -aim
: (offset..scale(1.0 / math.max(distance, 1e-6)));
final ratio = direction.w > 0.0 ? distance / direction.w : 0.0;
final window = (1.0 - ratio * ratio * ratio * ratio).clamp(0.0, 1.0);
final falloff = window * window / math.max(distance * distance, 1e-4);
final spot = type > 1.5 && type < 2.5;
final linearRamp = spot
? ((aim.dot(-toLight) - cone.y) / math.max(cone.x - cone.y, 1e-4)).clamp(
0.0,
1.0,
)
: 1.0;
final ramp = linearRamp * linearRamp;
// A plugin's light type (codes from 16 up) gives nothing here.
final attenuation = type > 15.5
? 0.0
: (directional ? 1.0 : (degenerate ? 0.0 : falloff * ramp));
return (
toLight: toLight,
radiance: Vector3(color.x, color.y, color.z) * (color.w * attenuation),
);
}