light: the pixel rides o/t, not a held chroma — SHADOW and BLACK drained a dark red to 0.505 of its saturation, it is 0.742 now
This commit is contained in:
@@ -139,24 +139,34 @@ float lin(float e0, float e1, float x) {
|
||||
// between 0.25 and 0.5, and DR's own shadow lift slopes DOWN through that
|
||||
// stretch, which is a fold at 0.238.
|
||||
//
|
||||
// Lightness takes the curve; the colour rides the difference. The pixel moves to
|
||||
// its new luma and carries its own chroma with it — the three channel
|
||||
// differences are scaled by ONE number, so the hue cannot move and a grey cannot
|
||||
// pick up a cast (a neutral has no difference to carry, and lands on o exactly).
|
||||
// Lightness takes the curve; the colour rides the ratio. The pixel moves to its
|
||||
// new luma, and it gets there by scaling its three channels by ONE number,
|
||||
// k = o / t: the doc's R_new = R_old * Luma_new / Luma_old. The differences move
|
||||
// with the light, so the hue cannot turn, the saturation cannot be drained by a
|
||||
// lift — an HSL saturation is a ratio of differences and never sees a common
|
||||
// scale — and a neutral, with no difference to carry, lands on o exactly.
|
||||
//
|
||||
// The doc's ratio (R_new = R_old * Luma_new / Luma_old) is the other reading of
|
||||
// the same sentence, and it is what this pass used to do. It is exact — until
|
||||
// the result stops fitting. Past 1.0 a channel clips, the differences stop being
|
||||
// scaled together, and the hue goes with them: measured on the scratchpad probe
|
||||
// (hl-variants.mjs), a skin tone at 24.0° came back at 48.0° at HIGHLIGHT +100,
|
||||
// and a warm white at 37° at 57.4°. Under L = 0.5 the same ratio also multiplies
|
||||
// whatever cast a near-black pixel had — x30 on a shadow with a hair of warmth,
|
||||
// which is colour noise amplified, the reason the old arbitrary 0.55..1.35 clamp
|
||||
// was there.
|
||||
// The scale used to be 1.0 instead: keep the chroma, move the luma. That holds
|
||||
// the hue and loses the colour, which is the complaint the ratio answers — the
|
||||
// scratchpad probe (sh-bl-hue.mjs) measured a dark red at 0.746 of saturation
|
||||
// coming back at 0.505 with SHADOW at +100, and at 0.370 with SHADOW and BLACK
|
||||
// both at +100. A chroma held under a rising luma IS a colour going grey, and it
|
||||
// is the two sliders that lift a shadow (SHADOW, BLACK) that raise the luma of a
|
||||
// dark pixel the furthest.
|
||||
//
|
||||
// So the scale is the chroma's own (1.0) and the only thing that pulls it back
|
||||
// is the cube: a pixel with no room left gives up saturation instead of hue, and
|
||||
// one that the curve has actually driven to 1.0 arrives at white.
|
||||
// What the ratio cannot do on its own is fit, and that is what the caps below are
|
||||
// for: past the ceiling a channel clips outright, the three stop being scaled
|
||||
// together and the hue goes with them (measured on the other probe, a skin tone
|
||||
// at 24.0° came back at 48.0° at HIGHLIGHT +100, a warm white at 37° at 57.4°).
|
||||
// Pulling the ONE scale back while the cube has room for no more costs saturation
|
||||
// instead: a pixel the cube is against arrives neutral before it arrives wrong,
|
||||
// and one the curve has driven all the way to 1.0 arrives at white.
|
||||
//
|
||||
// Below t = 0.0004 there is no ratio worth the name: dividing by what is left of
|
||||
// a pixel that has almost no light on it takes whatever cast the last code value
|
||||
// of 8-bit noise left there and multiplies it by the pedestal the BLACK knob just
|
||||
// lifted — colour noise, amplified to the size of the lift. The scale stays 1.0
|
||||
// down there and the pixel takes the pedestal as the flat grey it is.
|
||||
//
|
||||
// ONE move of the light, and everything in this file that changes how bright a
|
||||
// pixel is goes through it: a tone knob, a mask's tone knob, and the exposure
|
||||
@@ -166,7 +176,7 @@ float lin(float e0, float e1, float x) {
|
||||
// a channel reaches the ceiling, where the three clip by different amounts and
|
||||
// the hue goes with them.
|
||||
vec3 lightMove(vec3 c, float t, float o) {
|
||||
float k = 1.0;
|
||||
float k = t > 0.0004 ? o / t : 1.0;
|
||||
float hiC = max(max(c.r, c.g), c.b);
|
||||
float loC = min(min(c.r, c.g), c.b);
|
||||
if (hiC > t) k = min(k, (1.0 - o) / (hiC - t));
|
||||
|
||||
Reference in New Issue
Block a user