chore: deploy private lightloom build
Browse files- frontend/js/stage-scroll.js +22 -14
- src/lightloom/paint/scroll.py +3 -1
frontend/js/stage-scroll.js
CHANGED
|
@@ -42,11 +42,17 @@ const Scroll = (() => {
|
|
| 42 |
const MARCH_BIN = 7; // binary-refine steps inside the bracketed interval
|
| 43 |
const VEL_TAU = 0.18; // s — exponential smoothing time-const for scroll velocity
|
| 44 |
const VEL_REF = 220.0; // px/s mapped to full +/-1 parallax (scroll ~110px/s => ~0.5 budget)
|
| 45 |
-
const AERIAL_DESAT = 0.
|
| 46 |
-
//
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
const HAZE_TINT = [0.62, 0.68, 0.78]; // cool sky/haze tint
|
| 51 |
let imgCanvas = null, depCanvas = null, imgCtx = null, depCtx = null;
|
| 52 |
let imgTex = null, depTex = null;
|
|
@@ -106,6 +112,16 @@ const Scroll = (() => {
|
|
| 106 |
float d = pow(clamp(d0, 0.0, 1.0), uGamma);
|
| 107 |
return clamp(uFocus + (d - uFocus) * uGain, 0.0, 1.0);
|
| 108 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
void main(){
|
| 110 |
// view ray (parallax-occlusion): eyepoint shifts horizontally by P across the ray. ray param
|
| 111 |
// t in [0,1]; ray height descends 1 -> 0; surface = heightAt(baseUv - P*t). First t where
|
|
@@ -152,15 +168,7 @@ const Scroll = (() => {
|
|
| 152 |
c = mix(c, vec3(luma), uAerialDesat * farness);
|
| 153 |
c = mix(c, uHazeTint, uAerialHaze * farness * farness);
|
| 154 |
|
| 155 |
-
//
|
| 156 |
-
// so texture2D(uImg) returns the painter's already-sRGB bytes verbatim (Three.js only injects a
|
| 157 |
-
// sRGB->linear decode for BUILT-IN materials, never for a raw texture2D() in a ShaderMaterial),
|
| 158 |
-
// and this shader writes gl_FragColor straight to the framebuffer (no <colorspace_fragment>
|
| 159 |
-
// chunk -> the renderer adds no output conversion either). Applying toSRGB() here was a SECOND
|
| 160 |
-
// gamma OETF on top of the painter's: it lifted blacks 0.10->0.35 and mids 0.50->0.74, washing
|
| 161 |
-
// every scene to a milky grey fog (worst in shadows) while .stylegrid PNGs stayed vivid. Output
|
| 162 |
-
// the values as-is so on-screen color == the painter's color. (Aerial mixes above run in sRGB,
|
| 163 |
-
// fine for a subtle cue.)
|
| 164 |
c *= mix(0.92, 1.05, dHit); // near a touch brighter (aerial cue)
|
| 165 |
float vy = smoothstep(0.0, 0.12, vUv.y) * smoothstep(1.0, 0.88, vUv.y);
|
| 166 |
c *= mix(0.82, 1.0, vy);
|
|
|
|
| 42 |
const MARCH_BIN = 7; // binary-refine steps inside the bracketed interval
|
| 43 |
const VEL_TAU = 0.18; // s — exponential smoothing time-const for scroll velocity
|
| 44 |
const VEL_REF = 220.0; // px/s mapped to full +/-1 parallax (scroll ~110px/s => ~0.5 budget)
|
| 45 |
+
const AERIAL_DESAT = 0.04; // whisper far-plane desaturation (depth cue). Verified: at 0.04 far content
|
| 46 |
+
// keeps ~85-96% chroma; the near-brightness mix below also reads as depth.
|
| 47 |
+
const AERIAL_HAZE = 0.0; // OFF. This was THE grey-blue fog: HAZE_TINT below is a LINEAR color that
|
| 48 |
+
// DISPLAYS at [206,215,229]/255 (bright grey-blue) after toSRGB, and mixing
|
| 49 |
+
// it in LINEAR space lifts dark/shadow pixels ~4x (sRGB-16 -> ~53), so big
|
| 50 |
+
// "far" regions milked out. DepthAnything reads large painterly areas as far,
|
| 51 |
+
// spreading it everywhere. Lowering it (0.45->0.15->0.05) kept firing; ZERO is
|
| 52 |
+
// the qualitative fix (line below becomes a no-op). Verified twice: removes the
|
| 53 |
+
// cast completely, does NOT darken (haze/desat are pre-toSRGB; brightness term
|
| 54 |
+
// untouched), parallax geometry untouched.
|
| 55 |
+
const AERIAL_BLUR = 0.35; // texel-scale of the far-plane 4-tap micro-blur — spatial only, no desat
|
| 56 |
const HAZE_TINT = [0.62, 0.68, 0.78]; // cool sky/haze tint
|
| 57 |
let imgCanvas = null, depCanvas = null, imgCtx = null, depCtx = null;
|
| 58 |
let imgTex = null, depTex = null;
|
|
|
|
| 112 |
float d = pow(clamp(d0, 0.0, 1.0), uGamma);
|
| 113 |
return clamp(uFocus + (d - uFocus) * uGain, 0.0, 1.0);
|
| 114 |
}
|
| 115 |
+
// Linear -> sRGB OETF. REQUIRED: the strip CanvasTexture has colorSpace=SRGB, which in three r160
|
| 116 |
+
// uploads it as SRGB8_ALPHA8 (WebGLTextures.getInternalFormat, three.module.js:24171), so the GPU
|
| 117 |
+
// DECODES sRGB->linear on every texture2D(uImg) sample -> c is LINEAR here. This custom shader has
|
| 118 |
+
// no <colorspace_fragment> chunk, so the renderer adds no output encode. We must encode linear->sRGB
|
| 119 |
+
// ourselves or the framebuffer (outputColorSpace=SRGB) shows the picture ~2.2-gamma too dark.
|
| 120 |
+
vec3 toSRGB(vec3 c){
|
| 121 |
+
c = max(c, vec3(0.0));
|
| 122 |
+
vec3 lo = c * 12.92; vec3 hi = 1.055 * pow(c, vec3(1.0/2.4)) - 0.055;
|
| 123 |
+
return mix(lo, hi, step(vec3(0.0031308), c));
|
| 124 |
+
}
|
| 125 |
void main(){
|
| 126 |
// view ray (parallax-occlusion): eyepoint shifts horizontally by P across the ray. ray param
|
| 127 |
// t in [0,1]; ray height descends 1 -> 0; surface = heightAt(baseUv - P*t). First t where
|
|
|
|
| 168 |
c = mix(c, vec3(luma), uAerialDesat * farness);
|
| 169 |
c = mix(c, uHazeTint, uAerialHaze * farness * farness);
|
| 170 |
|
| 171 |
+
c = toSRGB(c); // linear -> sRGB for the framebuffer (see note above)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 172 |
c *= mix(0.92, 1.05, dHit); // near a touch brighter (aerial cue)
|
| 173 |
float vy = smoothstep(0.0, 0.12, vUv.y) * smoothstep(1.0, 0.88, vUv.y);
|
| 174 |
c *= mix(0.82, 1.0, vy);
|
src/lightloom/paint/scroll.py
CHANGED
|
@@ -119,7 +119,9 @@ def outpaint_right(
|
|
| 119 |
from PIL import Image
|
| 120 |
|
| 121 |
width = overlap + seg_w
|
| 122 |
-
|
|
|
|
|
|
|
| 123 |
mask = Image.new("L", (width, height), 255) # generate everything…
|
| 124 |
if context is not None:
|
| 125 |
ctx = context.crop((context.width - overlap, 0, context.width, context.height))
|
|
|
|
| 119 |
from PIL import Image
|
| 120 |
|
| 121 |
width = overlap + seg_w
|
| 122 |
+
# neutral grey base (matches the proven-vivid fresh/stylegrid path); the old blue-grey
|
| 123 |
+
# (90,105,120) is a saturated tint that can bleed at the first strip / disoccluded edges.
|
| 124 |
+
canvas = Image.new("RGB", (width, height), (128, 128, 128))
|
| 125 |
mask = Image.new("L", (width, height), 255) # generate everything…
|
| 126 |
if context is not None:
|
| 127 |
ctx = context.crop((context.width - overlap, 0, context.width, context.height))
|