From d7d7be2c6be11c99b413eba4b00a0bd755e1982e Mon Sep 17 00:00:00 2001 From: 3dtours Date: Fri, 18 Sep 2026 16:09:09 +0700 Subject: [PATCH] web: add CLASSIC VIVIDIPES, spliced at the blue row Classic Chrome's blue row, verbatim, with the red and green rows taken from VELVIPES: skies keep the muted teal/cyan lean while everything that is not blue reads loud. The shadow crush rides along from FILM_TONE, since it belongs to the stock rather than to a row. CLASSIC CHRIPES stays untouched beside it. --- docker/frontend/shared/types/index.ts | 2 +- docker/frontend/shared/utils/colorUtils.ts | 11 +++++++++++ docker/frontend/shared/utils/defaultRecipes.ts | 1 + docker/frontend/shared/utils/toneShader.ts | 3 +++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/docker/frontend/shared/types/index.ts b/docker/frontend/shared/types/index.ts index 9cffb4a..f16a24d 100644 --- a/docker/frontend/shared/types/index.ts +++ b/docker/frontend/shared/types/index.ts @@ -68,7 +68,7 @@ export const MIN_CROP_FRAC = 0.08; // cool tint in shade, plus a seasonal atmospheric haze/fog veil. export type CinemaSeason = 'spring' | 'summer' | 'autumn' | 'winter'; -export type BaseFilter = 'classic-neg' | 'classic-chrome' | 'provia' | 'velvia' | 'astia' | 'eterna' | 'monochrome' | 'leica' | 'leica-vivid' | 'none'; +export type BaseFilter = 'classic-neg' | 'classic-chrome' | 'classic-vivid' | 'provia' | 'velvia' | 'astia' | 'eterna' | 'monochrome' | 'leica' | 'leica-vivid' | 'none'; export interface ColorAdjustments { exposure: number; // -10 to +10 (mapped to matrix multiplier or offset) diff --git a/docker/frontend/shared/utils/colorUtils.ts b/docker/frontend/shared/utils/colorUtils.ts index 4a69a24..4d8dbf2 100644 --- a/docker/frontend/shared/utils/colorUtils.ts +++ b/docker/frontend/shared/utils/colorUtils.ts @@ -120,6 +120,17 @@ export function getSkiaColorMatrix(baseFilter: BaseFilter, adj: ColorAdjustments 0.0652, 0.3973, 0.5575, 0, -0.0100, 0, 0, 0, 1, 0, ]; + } else if (baseFilter === 'classic-vivid') { + // Classic Vivid: the Classic Chrome blue row kept verbatim — skies stay the + // same muted teal/cyan — with the red and green rows taken from Velvia, so + // everything that is not blue reads loud. Two stocks spliced at the blue + // row, which is exactly the point: quiet skies over saturated colour. + matrix = [ + 1.3895, -0.2540, -0.0256, 0, -0.0550, + -0.0772, 1.2355, -0.0261, 0, -0.0661, + 0.0652, 0.3973, 0.5575, 0, -0.0100, + 0, 0, 0, 1, 0, + ]; } else if (baseFilter === 'astia') { // Astia (Soft): gentler than standard — contrast below neutral (shadows // lift, highlights ease off) and colour held back, with a faint warm/pink diff --git a/docker/frontend/shared/utils/defaultRecipes.ts b/docker/frontend/shared/utils/defaultRecipes.ts index 22cb950..700978f 100644 --- a/docker/frontend/shared/utils/defaultRecipes.ts +++ b/docker/frontend/shared/utils/defaultRecipes.ts @@ -41,6 +41,7 @@ export const FILM_SIMS: FilmSim[] = [ { id: 'sim-provia', name: 'PROVIPES', baseFilter: 'provia', adjustments: { ...DEFAULT_ADJUSTMENTS } }, { id: 'sim-velvia', name: 'VELVIPES', baseFilter: 'velvia', adjustments: { ...DEFAULT_ADJUSTMENTS } }, { id: 'sim-classic-chrome', name: 'CLASSIC CHRIPES', baseFilter: 'classic-chrome', adjustments: { ...DEFAULT_ADJUSTMENTS } }, + { id: 'sim-classic-vivid', name: 'CLASSIC VIVIDIPES', baseFilter: 'classic-vivid', 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-eterna', name: 'ETERNIPES', baseFilter: 'eterna', adjustments: { ...DEFAULT_ADJUSTMENTS } }, diff --git a/docker/frontend/shared/utils/toneShader.ts b/docker/frontend/shared/utils/toneShader.ts index e1cf48c..4346215 100644 --- a/docker/frontend/shared/utils/toneShader.ts +++ b/docker/frontend/shared/utils/toneShader.ts @@ -207,6 +207,9 @@ export interface ToneUniforms { // without also moving the other. const FILM_TONE: Partial>> = { 'classic-chrome': { sh: -0.28 }, + // Classic Vivid is Classic Chrome's sibling — the shadow crush belongs to the + // stock, not to the matrix rows, so it comes along. + 'classic-vivid': { sh: -0.28 }, '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