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 length = math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  final scale = length > 0.0 ? 1.0 / length : 0.0;
  final dx = v[0] * scale;
  final dy = v[1] * scale;
  final dz = v[2] * scale;

  // The preset, off the varyings rather than out of a uniform block — see
  // [SkyVertexShader].
  final zenith = Vector4(v[3], v[4], v[5], v[6]);
  final horizon = Vector4(v[7], v[8], v[9], v[10]);
  final nadir = Vector4(v[11], v[12], v[13], v[14]);
  final sun = Vector4(v[15], v[16], v[17], v[18]);
  final glow = Vector4(v[19], v[20], v[21], v[22]);
  final disc = Vector4(v[23], v[24], v[25], v[26]);

  final height = dy.clamp(-1.0, 1.0);
  final far = height >= 0.0 ? zenith : nadir;
  final magnitude = height.abs();
  final t = magnitude * magnitude * (3.0 - 2.0 * magnitude);

  var r = horizon.x + (far.x - horizon.x) * t;
  var g = horizon.y + (far.y - horizon.y) * t;
  var bl = horizon.z + (far.z - horizon.z) * t;

  final towards = dx * sun.x + dy * sun.y + dz * sun.z;
  if (towards > 0.0) {
    final lobe = glow.w * math.pow(towards, sun.w).toDouble();
    r += glow.x * lobe;
    g += glow.y * lobe;
    bl += glow.z * lobe;
  }

  // `disc.y` is the width of the soft edge, not the outer cosine: see the
  // renderer, which writes it that way because a varying cannot carry two
  // cosines this close together.
  // A soft edge of nothing is a hard edge, not an absent sun — see the same
  // branch in `sky.frag`, which had the same hole.
  final edge =
      (disc.y > 0.0
          ? smoothstep(disc.x - disc.y, disc.x, towards)
          : (towards >= disc.x ? 1.0 : 0.0)) *
      disc.z;
  r += glow.x * edge;
  g += glow.y * edge;
  bl += glow.z * edge;

  // **The surface is left alone, and that is a transcription of a fix.** The
  // GLSL this mirrors used to declare a second output and write zero into it;
  // on Impeller, in the usual single-attachment pass, that killed the
  // process. Nothing is lost either way — the attachment is cleared to zero,
  // which is the value this was writing — and the two backends have to say
  // the same thing or the transcription stops being one.
  return Vector4(r, g, bl, 1.0);
}