run method

  1. @override
Vector4? run(
  1. Float32List v,
  2. ShaderBindings bindings,
  3. FragmentContext c
)
override

Returns linear RGBA for attachment zero. Null discards the fragment.

Implementation

@override
Vector4? run(Float32List v, ShaderBindings bindings, FragmentContext c) {
  final color = bindings.vec4('TransmittanceInfo', 'color', Vector4.zero());
  final light = bindings.vec4('TransmittanceInfo', 'light', Vector4.zero());
  final params = bindings.vec4('TransmittanceInfo', 'params', Vector4.zero());
  final opacity = color.w.clamp(0.0, 1.0);
  final transmission = params.x.clamp(0.0, 1.0);
  final map = bindings.textures['base_color_texture'];
  final texel = map?.sample(v[kVUv], v[kVUv + 1]) ?? Vector4.all(1.0);
  double body(double channel, double mapped) =>
      (1.0 - opacity) +
      opacity * transmission * math.max(channel, 0.0) * mapped;

  final normal = Vector3(v[kVNormal], v[kVNormal + 1], v[kVNormal + 2]);
  final length = normal.length;
  final facing = length > 0.0
      ? (normal.dot(Vector3(light.x, light.y, light.z)) / length).abs()
      : 1.0;
  final f0 = params.y.clamp(0.0, 1.0);
  final fresnel =
      f0 + (1.0 - f0) * math.pow(1.0 - facing.clamp(0.0, 1.0), 5.0);
  // What is reflected is lost only as far as it is turned away: 2 cos²θ
  // of it, held to one — `shadow_transmittance.frag` has the reasons.
  final lost = fresnel * math.min(2.0 * facing * facing, 1.0);
  // A caster whose photons are followed stops all of its light here.
  final stops = params.z > 0.5;
  double through(double channel, double mapped) => stops
      ? 0.0
      : math.sqrt(math.max(body(channel, mapped), 0.0)) * (1.0 - lost);
  return Vector4(
    0.0,
    1.0 - through(color.x, texel.x),
    1.0 - through(color.y, texel.y),
    through(color.z, texel.z),
  );
}