Give ACRIPES a straight BT.709 ramp and end-only tone
This commit is contained in:
+15
-10
@@ -172,17 +172,22 @@ export function getSkiaColorMatrix(baseFilter: BaseFilter, adj: ColorAdjustments
|
|||||||
0, 0, 0, 1, 0,
|
0, 0, 0, 1, 0,
|
||||||
];
|
];
|
||||||
} else if (baseFilter === 'monochrome') {
|
} else if (baseFilter === 'monochrome') {
|
||||||
// Acros: pure BT.709 grayscale, zero colour leakage. Contrast is a touch
|
// Acros: pure BT.709 grayscale, zero colour leakage, and NO gain or offset.
|
||||||
// above neutral and eased around mid-grey, so the darks keep texture
|
// The weights sum to 1.0 and the offset is 0, so this matrix is a straight
|
||||||
// instead of plugging to black. (Grain/sharpness stay the user's call —
|
// luminance readout: nothing clips at either end and every grey step the
|
||||||
// a film sim here is the colour grade only.)
|
// sensor recorded survives. (An earlier 1.10x / -0.05 version plugged every
|
||||||
const r = 0.2339;
|
// black below ~5% and blew every white above ~95% — exactly the fine
|
||||||
const g = 0.7867;
|
// graduation this stock is prized for.) The deep black and the highlight
|
||||||
const b = 0.0794;
|
// shoulder live in FILM_TONE (toneShader.ts), where the curve can be shaped
|
||||||
|
// one end at a time without touching the midtones. (Grain/sharpness stay
|
||||||
|
// the user's call — a film sim here is the colour grade only.)
|
||||||
|
const r = 0.2126;
|
||||||
|
const g = 0.7152;
|
||||||
|
const b = 0.0722;
|
||||||
matrix = [
|
matrix = [
|
||||||
r, g, b, 0, -0.05,
|
r, g, b, 0, 0,
|
||||||
r, g, b, 0, -0.05,
|
r, g, b, 0, 0,
|
||||||
r, g, b, 0, -0.05,
|
r, g, b, 0, 0,
|
||||||
0, 0, 0, 1, 0,
|
0, 0, 0, 1, 0,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-10
@@ -24,11 +24,12 @@ export const DEFAULT_ADJUSTMENTS: ColorAdjustments = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Standard Fuji film simulations. These are the fixed "look" presets shown at
|
// Standard Fuji film simulations. These are the fixed "look" presets shown at
|
||||||
// the front of the PRESETS chip row: tapping one applies the simulation via
|
// the front of the PRESETS chip row: tapping one applies the simulation — its
|
||||||
// its baseFilter colour matrix ONLY — every other knob resets to its neutral
|
// baseFilter colour matrix plus whatever the stock itself carries outside the
|
||||||
// default (0 / auto) so the sim is a clean starting point, never a baked
|
// matrix (its FILM_TONE curve, and a grain amount when the grain IS the look,
|
||||||
// recipe. Any look beyond the matrix (grain, DR, CC, contrast…) is added by
|
// as on Acros). Every other knob still resets to its neutral default (0 /
|
||||||
// the user afterwards.
|
// auto), so a sim is a clean starting point, never a baked recipe; any further
|
||||||
|
// look (DR, CC, contrast, more grain) is added by the user afterwards.
|
||||||
export interface FilmSim {
|
export interface FilmSim {
|
||||||
id: string; // Recipe-like id used only while the sim is the current selection
|
id: string; // Recipe-like id used only while the sim is the current selection
|
||||||
name: string;
|
name: string;
|
||||||
@@ -43,7 +44,7 @@ export const FILM_SIMS: FilmSim[] = [
|
|||||||
{ id: 'sim-classic-neg', name: 'CLASSIC NEGIPES', baseFilter: 'classic-neg', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
{ id: 'sim-classic-neg', name: 'CLASSIC NEGIPES', baseFilter: 'classic-neg', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
||||||
{ id: 'sim-astia', name: 'ASTIPES', baseFilter: 'astia', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
{ id: 'sim-astia', name: 'ASTIPES', baseFilter: 'astia', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
||||||
{ id: 'sim-eterna', name: 'ETERNIPES', baseFilter: 'eterna', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
{ id: 'sim-eterna', name: 'ETERNIPES', baseFilter: 'eterna', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
||||||
{ id: 'sim-acros', name: 'ACRIPES', baseFilter: 'monochrome', adjustments: { ...DEFAULT_ADJUSTMENTS } },
|
{ id: 'sim-acros', name: 'ACRIPES', baseFilter: 'monochrome', adjustments: { ...DEFAULT_ADJUSTMENTS, grain: 3 } },
|
||||||
// The rangefinder digital look (M/Q/SL) is not a film stock, so it ships as its own
|
// The rangefinder digital look (M/Q/SL) is not a film stock, so it ships as its own
|
||||||
// pair instead of one look that has to compromise:
|
// pair instead of one look that has to compromise:
|
||||||
// CLASSIC — the stock character: deep solid darks, natural shadows, rich but
|
// CLASSIC — the stock character: deep solid darks, natural shadows, rich but
|
||||||
@@ -150,15 +151,21 @@ export const DEFAULT_RECIPES: Recipe[] = [
|
|||||||
baseFilter: 'monochrome',
|
baseFilter: 'monochrome',
|
||||||
adjustments: {
|
adjustments: {
|
||||||
exposure: 0,
|
exposure: 0,
|
||||||
contrast: 4,
|
// Low: the deep black comes from FILM_TONE's toe and the micro-contrast
|
||||||
|
// from CLARITY, both of which add separation WITHOUT flattening the grey
|
||||||
|
// ramp. The old 4 / highlight 3 / shadow -2 stack was three global
|
||||||
|
// contrast moves on top of a matrix that was already clipping — it
|
||||||
|
// bought its deep black by throwing away every step below 9% and every
|
||||||
|
// one above 91%.
|
||||||
|
contrast: 2,
|
||||||
saturation: 0,
|
saturation: 0,
|
||||||
temperature: 5000,
|
temperature: 5000,
|
||||||
tint: 0,
|
tint: 0,
|
||||||
highlight: 3,
|
highlight: 0,
|
||||||
shadow: -2,
|
shadow: 0,
|
||||||
denoise: 0,
|
denoise: 0,
|
||||||
clarity: 3,
|
clarity: 3,
|
||||||
grain: 6,
|
grain: 5,
|
||||||
colorChrome: 'none',
|
colorChrome: 'none',
|
||||||
colorChromeBlue: 'none',
|
colorChromeBlue: 'none',
|
||||||
dynamicRange: 'auto',
|
dynamicRange: 'auto',
|
||||||
|
|||||||
@@ -189,6 +189,16 @@ export interface ToneUniforms {
|
|||||||
const FILM_TONE: Partial<Record<BaseFilter, Partial<ToneUniforms>>> = {
|
const FILM_TONE: Partial<Record<BaseFilter, Partial<ToneUniforms>>> = {
|
||||||
'classic-chrome': { sh: -0.28 },
|
'classic-chrome': { sh: -0.28 },
|
||||||
'classic-neg': { shT: [-0.018, 0.009, 0.013], hlT: [0.024, 0.008, -0.012] },
|
'classic-neg': { shT: [-0.018, 0.009, 0.013], hlT: [0.024, 0.008, -0.012] },
|
||||||
|
// Acros. A black-and-white stock IS its grey ramp, so this entry only shapes
|
||||||
|
// the two ENDS and leaves the middle an identity: a smooth shadow toe that
|
||||||
|
// reaches a true black (no film-base lift, no flat grey wash) and a highlight
|
||||||
|
// shoulder that stops just short of white instead of clipping a cloud to
|
||||||
|
// paper. Mid-tones see neither mask, so the ramp keeps every step the matrix
|
||||||
|
// handed over — which is what 'deep black' costs in a colour stock and does
|
||||||
|
// not have to cost here.
|
||||||
|
// Gains are TONE_SKSL's own (sh * 0.34, hl * 0.22), so -0.12 puts the toe at
|
||||||
|
// ~5% and -0.05 trims the top ~1%.
|
||||||
|
monochrome: { sh: -0.12, hl: -0.05 },
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getToneUniforms(adj: ColorAdjustments, baseFilter?: BaseFilter): ToneUniforms {
|
export function getToneUniforms(adj: ColorAdjustments, baseFilter?: BaseFilter): ToneUniforms {
|
||||||
|
|||||||
Reference in New Issue
Block a user