run method

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

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

Implementation

@override
Vector4? run(Float32List v, ShaderBindings b, FragmentContext c) {
  final picture = b.textures['reflection_texture'];
  if (picture == null) return Vector4.zero();
  final view = b.vec4('PlanarReflectionInfo', 'view', Vector4(0, 0, 1, 1));
  final params = b.vec4('PlanarReflectionInfo', 'params', Vector4.zero());
  final tint = b.vec4('PlanarReflectionInfo', 'tint', Vector4.zero());

  // `FragCoordFromTop`, and the texture's rows turned back where its first
  // row is the bottom of the picture.
  final rows = params.z;
  final pixelY = rows > 0.0 ? rows - c.coord.y : c.coord.y;
  final u = (c.coord.x - view.x) / view.z;
  final top = (pixelY - view.y) / view.w;
  final texel = picture.sample(u, rows > 0.0 ? 1.0 - top : top);
  final reflected = Vector3(
    texel.x * tint.x,
    texel.y * tint.y,
    texel.z * tint.z,
  );

  final normal = Vector3(v[kVNormal], v[kVNormal + 1], v[kVNormal + 2])
    ..normalize();
  if (!c.frontFacing) normal.negate();
  final toEye = towardsEye(v, b);
  final cosine = normal.dot(toEye).clamp(0.0, 1.0);
  final f0 = params.x;
  final grazing = 1.0 - cosine;
  final grazing2 = grazing * grazing;
  final fresnel = f0 + (1.0 - f0) * grazing2 * grazing2 * grazing;
  final alpha = (fresnel * params.y).clamp(0.0, 1.0);

  final fogged = applyFog(reflected, v, b);
  return Vector4(fogged.x * alpha, fogged.y * alpha, fogged.z * alpha, alpha);
}