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 power = -0.5 * (v[4] * v[4] + v[5] * v[5]);
  if (power < -4.5) return null;

  final alpha = v[3] * math.exp(power);
  if (alpha < 1.0 / 255.0) return null;

  // The splat's identity as a whole number — millimetres along the view
  // axis, the colour in 8-bit steps — and the offset into the noise it
  // hashes to.
  final eye = b.vec4('SplatHashInfo', 'eye', Vector4.zero());
  final forward = b.vec4('SplatHashInfo', 'forward', Vector4.zero());
  final along =
      (v[6] - eye.x) * forward.x +
      (v[7] - eye.y) * forward.y +
      (v[8] - eye.z) * forward.z;
  final identity =
      ((along * 1000.0).floorToDouble() +
          (v[0] * 255.0 +
                  v[1] * 255.0 * 7.0 +
                  v[2] * 255.0 * 31.0 +
                  v[3] * 255.0 * 127.0)
              .floorToDouble()) %
      4096.0;
  final (offsetX, offsetY) = splatNoiseOffset(identity);

  // This frame's slice of the blue noise, at the pixel moved by the offset.
  final table = b.textures['blue_noise_texture'];
  if (table == null) return null;
  final frame = b.vec4('SplatHashInfo', 'frame', Vector4.zero());
  final slice = frame.x;
  // `FragCoordFromTop`.
  final row = frame.y > 0.0 ? frame.y - c.coord.y : c.coord.y;
  final cellX = (c.coord.x.floorToDouble() + offsetX) % 64.0;
  final cellY = (row.floorToDouble() + offsetY) % 64.0;
  final cornerX = (slice % 8.0).floorToDouble() * 64.0;
  final cornerY = (slice / 8.0).floorToDouble() * 64.0;
  final threshold =
      table
          .sample(
            (cornerX + cellX + 0.5) / 512.0,
            (cornerY + cellY + 0.5) / 256.0,
          )
          .x *
      (255.0 / 256.0);

  if (alpha <= threshold) return null;

  final fog = b.vec4('FogInfo', 'fog', Vector4.zero());
  if (fog.w <= 0.0) return Vector4(v[0], v[1], v[2], 1.0);
  final d = fogDistance(b, v[6], v[7], v[8]);
  final visibility = math.exp(-fog.w * d).clamp(0.0, 1.0);
  return Vector4(
    fog.x + (v[0] - fog.x) * visibility,
    fog.y + (v[1] - fog.y) * visibility,
    fog.z + (v[2] - fog.z) * visibility,
    1.0,
  );
}