WIP: noise reduction

Checkpoint committed by the coordinator, not by the authoring agent: the
session hit its API limit mid-task and left this work uncommitted. Committed
so it survives, NOT because it is finished - expect failing tests and
half-applied changes. The agent resumes from here.
This commit is contained in:
2026-08-22 19:01:18 +02:00
parent c963dafd09
commit b4e55b47c1
6 changed files with 1469 additions and 5 deletions
+3 -1
View File
@@ -211,7 +211,9 @@ half in Rust would be worse than either alone.
Currently hand-written: `tone_curve` (a curve widget over five interpolated
points), `colour_mixer` (thirty-six faceted parameters from twelve computed hue
bands). `vignetting` is hand-written too but is not in the develop chain — it
bands), and `noise_reduction` (a kernel, and one that decides how many
dispatches to emit at each resolution — see the next section).
`vignetting` is hand-written too but is not in the develop chain — it
carries lens-profile coefficients that are not parameters. `distortion` and
`aberration` are `Warp`s rather than operations: they rewrite coordinates
before sampling rather than transforming a colour after it.
+30
View File
@@ -0,0 +1,30 @@
# A hand-written node. `rust:` names the type in `crate::ops` that implements
# `Operation`; its descriptor, its parameters and its passes come from that
# type rather than from this file.
#
# It appears here anyway so that `ops/` lists the whole pipeline in order —
# including the neighbourhood operations, which run as a group after every
# point operation but are still ordered among themselves.
id: noise_reduction
order: 110
rust: NoiseReduction
why_rust: |
A kernel, not four facts. The declarative schema hands a fragment a colour
and no coordinate, which is precisely what a denoiser cannot work with — it
is defined by what the neighbouring pixels are doing. It is therefore a
`DetailStage` (see `../src/detail.rs`), which means deciding at every render
how many dispatches to emit, converting a radius stated in *source* pixels
into the render pixels this frame is being drawn at, and declaring the halo
the tile scheduler needs. None of that is expressible as a uniform
expression, and stretching the schema to cover it would produce a worse
language than Rust aimed at one caller.
placement: |
First among the detail operations, because denoising is a repair and
everything else in this stage is an enhancement: sharpening or adding
clarity to a noisy frame amplifies the grain along with the detail, and no
later pass can separate them again. Its position relative to the point
operations is not this number's to decide — the whole detail stage runs
after the fused pass, in linear light, before the output transform.