Feat: Add post-tone-map mesh diagnostics with RGBA overlays

Color antialiased half-edges by ray outcome with configurable Catppuccin colors and default opacity 0.5.

Rasterize premultiplied RGBA8 overlays on the producer and composite in place after writing the clean image. Keep single-frame, movie, and replay output consistent.

Add overlay, CLI, and queue ownership regressions and document the final output architecture.
This commit is contained in:
wyj committed 2026-10-10 01:46:32 -04:00
1 parent 4053d5d0c8
commit 80f9dcb3a3
17 files changed
+1873 -182

No files matched your search

+35 -3
View File
@@ -614,13 +614,45 @@ the sum of producer frame times only (it excludes tracing, prefetch, and the
final queue drain). The all-sky `Movie catalog prefetch:` line reports mark,
load+commit, and total tile time. Timing uses one clock read per bulk phase,
never inside the per-star or per-pixel hot loops.
With `--draw-mesh`, tone mapping runs only once per frame. The async writer
writes the clean RGB8 image first, then composites the producer-rasterized
premultiplied RGBA8 layer in place and writes the mesh sibling. Mesh preparation
and rasterization are included in the producer's frame total; composition and
image output are included in the writer summary.
Pass `--draw-mesh` to also write the final image-plane triangle mesh as a
`<output-stem>_mesh.png` sibling (`.ppm` in non-PNG builds). The main
tone-mapped image and any `--hdr-output` FITS file remain mesh-free. The
overlay alpha-composites image-plane triangle edges as one-pixel-wide 0.5
linear-gray diagnostic lines at 0.5 opacity. The line rasterizer uses
coverage-based antialiasing.
overlay alpha-composites one-pixel-wide, coverage-antialiased triangle edges
onto the final sRGB8 image **after** sensor bloom, tone mapping, and the sRGB
transfer, preserving mesh contrast on saturated highlights. Each vertex colors
its incident half-edges; differently classified endpoints switch color at the
edge midpoint. Shared edges are drawn once. The premultiplied sRGB RGBA8 layer
uses source-over accumulation and composition, with the same rules for
single-frame, movie, and replay output.
The default palette is Catppuccin Mocha, with opacity `0.5`:
| Vertex category | Default color | CLI override |
| --- | --- | --- |
| `ESCAPED` | Overlay1 `#7F849C` (gray) | `--mesh-color-escape` |
| `DARK` | Mauve `#CBA6F7` (purple) | `--mesh-color-dark` |
| `UNRESOLVED` | Yellow `#F9E2AF` | `--mesh-color-unresolved` |
| `INCOMPLETE` | Red `#F38BA8` | `--mesh-color-incomplete` |
| Untraced | Blue `#89B4FA` | `--mesh-color-untraced` |
Color arguments are strict sRGB `#RRGGBB` values; quote them in the shell.
`--mesh-opacity` accepts a finite number in `[0,1]`. These settings do not
implicitly enable `--draw-mesh`. For example:
```sh
--draw-mesh --mesh-color-dark '#CBA6F7' --mesh-color-unresolved '#F9E2AF' --mesh-opacity 0.8
```
`UNRESOLVED` denotes trustworthy trajectories with exhausted compute budgets
(not just accepted-step limits), while `INCOMPLETE` denotes actual history,
domain, metric, integration, I/O, or protocol failures. Different dark reasons
share one color. Coloring is a read-only visualization of the finalized mesh.
Normal progress and summaries go to stdout; warnings, errors, and Debug
diagnostics go to stderr. Successful runs exit `0` even if warnings are emitted.