packUniforms method
Packs the custom float uniforms in shader declaration order.
The engine owns float uniforms 0 and 1 (the filter input size) and sampler
0 (the filter input itself), so these fourteen land at indices 2 through
15.
The last six are the surround and haze colours, three components each. The
shader declares all six as separate scalars rather than two vec3s: a
vector uniform is padded and aligned by the backend, and these are
addressed by float index, so a padded vector silently shifts every uniform
after it. uLiftDirX and uLiftDirY are split for the same reason.
tiltDegrees is clamped to plus or minus maxTiltDegrees and then
reported to the shader as a magnitude: direction lives in liftDirX and
liftDirY instead of in the sign, so a negative tiltDegrees and a
positive one of the same size pack identically unless the lift direction
also differs.
pixelsPerMillimeter must already be a resolved, finite, positive value:
this method clamps it away from zero but does not guard against NaN,
since math.max propagates NaN rather than rejecting it. Callers must
route the raw density through resolvePixelsPerMillimeter first; do not
pass a platform-reported or user-supplied value straight through.
Implementation
List<double> packUniforms({
required double tiltDegrees,
required double liftDirX,
required double liftDirY,
required double pixelsPerMillimeter,
}) {
final clampedTilt = tiltDegrees
.clamp(-maxTiltDegrees, maxTiltDegrees)
.toDouble();
final shapedTilt = _shape(clampedTilt.abs());
final density = math.max(pixelsPerMillimeter, 1e-6);
return <double>[
shapedTilt,
liftDirX,
liftDirY,
eyeDistanceMillimeters * density,
blurSpread,
darkening * referencePixelsPerMillimeter / density,
surroundColor.r,
surroundColor.g,
surroundColor.b,
hazeColor.r,
hazeColor.g,
hazeColor.b,
baseBlurMillimeters * density,
stretchEdges ? 1.0 : 0.0,
];
}