feat(studio & library): sync Light & Color tab parameters (vibrance, highlight, shadow, white, black) to Gradient Mask & add multi-field sorting options
This commit is contained in:
@@ -82,6 +82,7 @@ export type ReadMask = GradientMask & {
|
||||
blacks: number;
|
||||
clarity: number;
|
||||
dehaze: number;
|
||||
vibrance: number;
|
||||
temperature: number;
|
||||
tint: number;
|
||||
};
|
||||
@@ -100,18 +101,19 @@ export function readMasks(masks: GradientMask[] | undefined): ReadMask[] {
|
||||
ry: Math.max(0, num(m.ry, 0)),
|
||||
angle: num(m.angle, 0),
|
||||
feather: clamp01(num(m.feather, MASK_DEFAULT_FEATHER)),
|
||||
exposure: clampEV(num(m.exposure, 0)),
|
||||
exposure: clampEV(num(m.exposure ?? (m as any).ev, 0)),
|
||||
contrast: clampA(num(m.contrast, 0)),
|
||||
saturation: clampA(num(m.saturation, 0)),
|
||||
saturation: clampA(num(m.saturation ?? (m as any).color, 0)),
|
||||
// The spec's section 4 knobs: the two tone soft masks, the two ends, and
|
||||
// the two spatial moves. All -10..+10 like every other knob here, all 0 on
|
||||
// a mask stored before they existed.
|
||||
highlights: clampA(num(m.highlights, 0)),
|
||||
shadows: clampA(num(m.shadows, 0)),
|
||||
whites: clampA(num(m.whites, 0)),
|
||||
blacks: clampA(num(m.blacks, 0)),
|
||||
highlights: clampA(num(m.highlights ?? m.highlight, 0)),
|
||||
shadows: clampA(num(m.shadows ?? m.shadow, 0)),
|
||||
whites: clampA(num(m.whites ?? m.white, 0)),
|
||||
blacks: clampA(num(m.blacks ?? m.black, 0)),
|
||||
clarity: clampA(num(m.clarity, 0)),
|
||||
dehaze: clampA(num(m.dehaze, 0)),
|
||||
vibrance: clampA(num(m.vibrance, 0)),
|
||||
// The WB pair, the two rulers the LIGHT column already carries, read on the
|
||||
// mask's own pixels: kelvin on its own scale, tint in the store's ±10. Both
|
||||
// absent on a mask stored before they existed, and then the gain is 1.
|
||||
@@ -158,9 +160,9 @@ export function maskUniforms(
|
||||
[m.exposure, m.contrast / 10, m.saturation / 10, MASK_KIND[m.kind]],
|
||||
(2 * n + i) * 4
|
||||
);
|
||||
// The tone soft masks and the two ends, then the spatial pair.
|
||||
// The tone soft masks and the two ends, then the spatial pair & vibrance.
|
||||
u.set([m.highlights / 10, m.shadows / 10, m.whites / 10, m.blacks / 10], (3 * n + i) * 4);
|
||||
u.set([m.clarity / 10, m.dehaze / 10, 0, 0], (4 * n + i) * 4);
|
||||
u.set([m.clarity / 10, m.dehaze / 10, m.vibrance / 10, 0], (4 * n + i) * 4);
|
||||
// The mask's own white balance, resolved here and not in the shader: the
|
||||
// Kelvin fit is a curve, and a curve in SkSL would be a second copy of it
|
||||
// (colorUtils.whiteBalanceGain is the one). Three gains and a zero pad, so
|
||||
@@ -212,17 +214,15 @@ half3 maskAdjust(half3 c, half3 wb, float4 a, float4 tone, float4 fx, half dark$
|
||||
// ordering clamp, the 0.50 midpoint no knob reaches, and the luma-preserving
|
||||
// rebuild are all the frame's. DR is the one knob the ramp also carries that a
|
||||
// mask does not have, so it is spent as 0 here.
|
||||
//
|
||||
// The BASE of that ramp is the mask's own pixel, handed in twice: a mask runs
|
||||
// on the shape the user drew and has no neighbourhood of its own, and the
|
||||
// degenerate call is the one the shared maths is written to take — a base equal
|
||||
// to t is a ratio of exactly 1, so the mask keeps the global move it has always
|
||||
// made. Give it a base of its own when a mask's SHADOW is reported the way the
|
||||
// frame's was.
|
||||
float lf = clamp(float(l), 0.0, 1.0);
|
||||
c = half3(toneRamp(vec3(c), lf, lf, tone.w, tone.y, tone.x, tone.z, 0.0));
|
||||
half nl = dot(clamp(c, half3(0.0), half3(1.0)), half3(0.2126, 0.7152, 0.0722));
|
||||
c = mix(half3(nl), c, half(1.0 + a.z));
|
||||
// Saturation & Vibrance matching toneShader's exact chroma-masked formula
|
||||
half mx = max(max(c.r, c.g), c.b);
|
||||
half mn = min(min(c.r, c.g), c.b);
|
||||
half chroma = mx > half(0.0001) ? (mx - mn) / mx : half(0.0);
|
||||
half kv = half(1.0) + half(fx.z) * half(0.75) * (half(1.0) - chroma);
|
||||
c = clamp(mix(half3(nl), c, half(1.0 + a.z) * kv), half3(0.0), half3(1.0));
|
||||
${spatial ? ` // DEHAZE before CLARITY, the frame-wide order and for the frame-wide reason:
|
||||
// sharpening haze only makes it read as detail.
|
||||
if (fx.y != 0.0) {
|
||||
|
||||
Reference in New Issue
Block a user