fix(raw): keep the blown highlights neutral after the tone curve
The blown gate draws a clipped pixel at its own maximum -- one value across the three channels, so the frame's highlights carry no cast -- but the per-channel tone curve runs after it and re-tints what the gate had just made neutral. One cubic a channel, fitted on a grid that has no block left to fit where the frame ran out (previewMatch drops the fully blown ones), so at the plateau the three curves agree only at 1.0 and part company either side of it. On the ORF this was reported on, the moonlit sky came back 254,255,255 and 253,255,254 -- red under green across a quarter of the frame. The gate is the develop's own statement that the pixel had no colour of its own, so it is re-read on the value that leaves the shader. The blown pixels now measure 254.95,254.94,254.97 (R/G 1.0000) against 253.44,254.94,254.51 (0.9941) before; their two most common triples, 254,255,255 at 149315 and 253,255,254 at 122127, collapse to 255,255,255 at 278099. The bright bands land at -0.0,-0.0,-0.0 against the embedded preview where they were -2.1,-0.0,-1.0, and midtones and the lower half are untouched.
This commit is contained in:
@@ -140,7 +140,8 @@ half4 main(float2 pos) {
|
||||
// mx is the value to hold: it is the pixel's own lightness.
|
||||
float hi = max(max(n.r, n.g), n.b);
|
||||
hi = max(hi, max(max(lin.r, lin.g), lin.b));
|
||||
rgb = mix(rgb, float3(mx), smoothstep(0.99, 1.02, hi));
|
||||
float blown = smoothstep(0.99, 1.02, hi);
|
||||
rgb = mix(rgb, float3(mx), blown);
|
||||
// The overflow used to fade towards white — mix(rgb / mx, 1, 1 - 1 / mx) —
|
||||
// which put every pixel of a blown sky on exactly 1.0 and threw the two stops
|
||||
// the sensor held above white away with it: LIGHT's HIGHLIGHT row then had a
|
||||
@@ -173,7 +174,15 @@ half4 main(float2 pos) {
|
||||
// fitted against (see previewMatch.ts). No rolloff: white is one of the values
|
||||
// the curve is fitted on, and it is pinned there, so a blown pixel still lands on
|
||||
// white while the frame's own highlights stay where the knee above left them.
|
||||
return half4(half3(tone(t0, e.r), tone(t1, e.g), tone(t2, e.b)), 1.0);
|
||||
float3 o = float3(tone(t0, e.r), tone(t1, e.g), tone(t2, e.b));
|
||||
// ...and the neutral the gate above drew is what the curve undoes: one cubic a
|
||||
// channel, fitted on a grid that has no block left to fit where the frame ran out
|
||||
// (the blown blocks are excluded, see previewMatch), so at the plateau the three
|
||||
// curves agree only at 1.0 and part company either side of it — measured on the
|
||||
// ORF, a 255,255,255 sky came back 254,255,255 and 253,255,254, red under green
|
||||
// across a quarter of the frame. The gate is the develop's own statement that the
|
||||
// pixel had no colour of its own, so it is re-read here, on the value that leaves.
|
||||
return half4(half3(mix(o, float3(max(max(o.r, o.g), o.b)), blown)), 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user