Replace the per-body base curve with a scene-referred view transform
The base curve was a five-point spline on the unit square, flat past its last point: every value above 1.0 left it as the same number, per channel. Exposure and highlight recovery put values up there, and the curve threw them away, then handed the result on as though it were still scene-linear. The six per-body curves were also, by their own file's account, hand-tuned shapes rather than measurements, and not enough is known about where they came from to keep them (D19). In their place, one view transform for every body (FR-DEV-3j): a log-logistic sigmoid per channel, with the middle channel put back between the other two so a hue survives the shoulder. Its two free constants are solved from two conditions rather than set: scene grey 0.13, where the retired default curve put it, lands on display 0.18, and the scene white four stops above grey lands on 1.0. So a highlight a stop past sensor saturation still rolls into white, and the midtones stay within 0.26 EV of the retired default between scene 0.03 and 1.0. `dr_pipeline::view` holds the CPU reference and the WGSL, and the tests there are FR-DEV-3j's acceptance criteria. It is still fixed and still in the fused pass's tail, so a detail stage still sees rendered values; the next commits make it an operation and move it after the detail stage. It is skipped for a JPEG, as the base curve was, and absent from the camera-space tap. The base curve's database, its lookup and its twelve uniform slots go. `RawImage` and `DemosaicedImage` lose the field, and the GPU test that proved a curve reached the shader is replaced by one that renders the view transform against the CPU reference and shows two highlights above 1.0 still render apart. The JPEG-and-sensor test now asserts the two differ by exactly the view transform, where before an identity fixture curve had made them match.
This commit is contained in:
@@ -452,7 +452,7 @@ exactly the stall §6.1 exists to prevent.
|
||||
**Two reductions, not one.** The display histogram (FR-DSP-7) counts the frame the output transform
|
||||
produced: its axis is the output code value, and a clipped bin means a highlight that is gone as the
|
||||
image currently stands. The raw histogram for culling (FR-CULL-3) counts the **demosaiced
|
||||
scene-linear texture** — before white balance, the camera matrix, the base curve and the tone chain
|
||||
scene-linear texture** — before white balance, the camera matrix, the tone chain and the view transform
|
||||
— on an axis of stops below sensor saturation, which is how it reports headroom the embedded JPEG's
|
||||
histogram cannot. A culling decision needs the second, an export decision needs the first, and
|
||||
neither answers for the other. Both are drawn by the same panel and chosen between.
|
||||
|
||||
@@ -446,8 +446,8 @@ reading a flag.
|
||||
|
||||
After the output transform, immediately before the clip and the encode — not
|
||||
among the layer blocks. Everything there runs on scene-referred colour in the
|
||||
working space, where a flat tint would be pushed through the base curve and
|
||||
the camera matrix and arrive as some other colour, and an alpha's white on
|
||||
working space, where a flat tint would be pushed through the view transform
|
||||
(the base curve and the camera matrix, before D19) and arrive as some other colour, and an alpha's white on
|
||||
black would arrive as neither.
|
||||
|
||||
### 6.3 Not on the graph
|
||||
|
||||
@@ -128,7 +128,11 @@ stays hot for it.
|
||||
### 5.1 The tap — S15.3, answered by reading the composer
|
||||
|
||||
The fused shader's order, fixed by `operation.rs`'s own tests: warp → as-shot
|
||||
white balance → operations → base curve → camera matrix → store. The store is
|
||||
white balance → operations → base curve → camera matrix → store. *(Amended
|
||||
2026-09-27, D19: warp → as-shot white balance → white balance → camera matrix
|
||||
→ operations → view transform → store. The tap is unaffected: it has no
|
||||
operations, its caller fills the matrix with the identity, and the composer
|
||||
emits no view transform in `OutputMode::CameraLinear`.)* The store is
|
||||
either the display encode or, in `OutputMode::LinearWorking`, an unclipped
|
||||
`rgba16float` of linear sRGB. That mode exists for the detail stage and is
|
||||
selected from the operations, never by a caller flag, so that a shader and
|
||||
@@ -155,7 +159,7 @@ FR-MRG-11 already bounds.
|
||||
|
||||
**What the DNG carries as a consequence:** the first source's `Make`,
|
||||
`Model` and `UniqueCameraModel` — so `base_curve::for_body` finds the 6D's
|
||||
curve — its `ColorMatrix1`/`2` with illuminants, and its `AsShotNeutral`. The
|
||||
curve (retired with the base curves, D19) — its `ColorMatrix1`/`2` with illuminants, and its `AsShotNeutral`. The
|
||||
composite then develops through the same profile as its sources, applied
|
||||
once. The spike's 64 × 48 file (§8) already carries the matrix and neutral;
|
||||
the body name is a string.
|
||||
|
||||
+36
-36
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user