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) {
  var du = 0.0;
  var dv = 0.0;
  final ddx = c.ddx;
  final ddy = c.ddy;
  if (ddx != null && ddy != null) {
    du = math.max(ddx[4].abs(), ddy[4].abs());
    dv = math.max(ddx[5].abs(), ddy[5].abs());
  }
  Vector4 read(String name) =>
      b.textures[name]?.sample(v[4], v[5], du: du, dv: dv) ??
      Vector4(1.0, 1.0, 1.0, 1.0);
  final positive = read('six_way_positive');
  final negative = read('six_way_negative');

  final right = b.vec4(_block, 'right', Vector4.zero()).xyz;
  final up = b.vec4(_block, 'up', Vector4.zero()).xyz;
  final forward = b.vec4(_block, 'forward', Vector4.zero()).xyz;
  double response(Vector3 l) {
    final x = l.dot(right);
    final y = l.dot(up);
    final z = l.dot(forward);
    return x * x * (x > 0.0 ? positive.x : negative.x) +
        y * y * (y > 0.0 ? positive.y : negative.y) +
        z * z * (z > 0.0 ? positive.z : negative.z);
  }

  final world = Vector3(v[6], v[7], v[8]);
  final lit = Vector3.zero();
  final count = contributorLightCount(b, world);
  for (var i = 0; i < count; i++) {
    final light = contributorLight(b, i, world);
    lit.addScaled(light.radiance, response(light.toLight));
  }

  final mean =
      (positive.x +
          positive.y +
          positive.z +
          negative.x +
          negative.y +
          negative.z) /
      6.0;
  final ambient = b.vec4(_block, 'ambient', Vector4.zero());
  final emission = b.vec4(_block, 'emission', Vector4.zero());
  final color = Vector3(
    v[0] * (lit.x + ambient.x * mean) + emission.x * negative.w,
    v[1] * (lit.y + ambient.y * mean) + emission.y * negative.w,
    v[2] * (lit.z + ambient.z * mean) + emission.z * negative.w,
  );

  // A mix toward the fog, not the additive stages' attenuation: this one
  // covers what is behind it.
  final fog = b.vec4('FogInfo', 'fog', Vector4.zero());
  if (fog.w > 0.0) {
    final d = fogDistance(b, world.x, world.y, world.z);
    final fogged = math.exp(-fog.w * d).clamp(0.0, 1.0);
    color
      ..x = fog.x + (color.x - fog.x) * fogged
      ..y = fog.y + (color.y - fog.y) * fogged
      ..z = fog.z + (color.z - fog.z) * fogged;
  }

  // Coverage, not colour: the blend is premultiplied, so a fading puff has
  // to let what is behind it through as well.
  final coverage =
      (v[3] * positive.w).clamp(0.0, 1.0) *
      (soft ? softParticleFade(b, c, v[6], v[7], v[8]) : 1.0);
  return Vector4(
    color.x * coverage,
    color.y * coverage,
    color.z * coverage,
    coverage,
  );
}