mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-07 04:12:15 +00:00
068c46cf8b
* Render: restore saved shots, progressive images and exports * Render: register existing live and coat command tests * Render: isolate lens saves and retain bounded previews Save only lens parameters on existing CPU/GPU jobs while keeping unrelated draft settings dirty. Retain pinned checkpoints through preview and status, and release host-only snapshots outside the status lock. Use the admitted PNG bound for registered-executor checkpoint slots. Preserve executor work credits, final publication and regrade ownership. Add regression coverage and align help, translations and capability documentation. * Render: preserve live feedback and address review regressions * Preserve saved cameras when applying Render library edits Keep the saved camera when lighting or maps are applied to an existing shot. Fit and centre the measured Render host using the painted picture. Carry forward the upstream CPU and GPU preset and ZoomTool contracts.
151 lines
9.7 KiB
Markdown
151 lines
9.7 KiB
Markdown
# HDR environment sampling (#1693)
|
|
|
|
Source implementation and opt-in CPU direct-light consumer are prepared. No
|
|
executed HDR-lit PNG, test, full gate or delivered HDRI feature is claimed. The
|
|
existing default preview remains unchanged.
|
|
|
|
`lighting::environment_sampling::EnvironmentPreparation` borrows an existing
|
|
`DecodedHdr`. It checks bounded 2:1 dimensions and original pixel allocation
|
|
capacity, then validates at most 16,384 pixels per step. The caller supplies a
|
|
fallible work/cancellation callback, charged for each inspection. Errors consume
|
|
preparation; `finish` refuses incomplete validation. No decoder, cache, CDF,
|
|
pixel clone, worker or pool is added. The existing owner and admission lease must
|
|
outlive the borrowed view. `retained_pixel_bytes` reports capacity, not length;
|
|
the host charges the owner for its retained lifetime. Captured image storage is
|
|
released before PNG publication; retained capture metadata has its own Record lease.
|
|
|
|
## Coordinates and estimator
|
|
|
|
Directions point away from the shading point. The map is Z-up: +Z is north,
|
|
`phi=atan2(y,x)`, `u=wrap(phi/(2*pi))`, `v=acos(z)/pi`. Nearest lookup uses
|
|
half-open texel cells centred on `((x+.5)/width,(y+.5)/height)`. Longitude wraps,
|
|
the south pole clamps to the last row, and an exact pole chooses longitude zero
|
|
before rotation. Positive rotation turns the environment about +Z toward +Y;
|
|
lookup subtracts that rotation. There is no extra orientation inherited from an
|
|
external application's conventions.
|
|
|
|
The first proposal samples uniform z in (-1,1) and phi in (0,2*pi). Since
|
|
`dOmega=dphi*dz`, its PDF is `1/(4*pi)` per steradian everywhere. The PDF remains
|
|
normalized for black maps, without a division by total image brightness. Constant
|
|
maps preserve their radiance. This is not importance sampling; small bright
|
|
sources can have high variance. Nearest lookup is intentionally not bilinear
|
|
filtering or a claim of antialiasing. Floating-point boundary rounding can still
|
|
produce a pole, whose lookup is defined.
|
|
|
|
`direct_sample_linear_srgb` returns an unoccluded `BRDF*cos*Li/pdf` estimate.
|
|
The geometric normal excludes incident and view directions crossing the original surface;
|
|
the shading normal affects the BRDF and cosine. The consumer owns visibility and
|
|
averages exactly once over the requested environment sample count. The helper
|
|
does not apply exposure, mapping, sRGB encoding or a sample-count division.
|
|
|
|
## Colour policy
|
|
|
|
Decoded HDR is linear RGB in its SOURCE space. RGBE decoding has already divided
|
|
by the file's exposure and colour correction; sampling never repeats either.
|
|
Source-space lookup is explicitly named `radiance_source_rgb`.
|
|
|
|
The initial lighting adapter admits only explicit `PRIMARIES` values matching
|
|
sRGB/D65: `0.64 0.33 0.30 0.60 0.15 0.06 0.3127 0.3290`. It uses these linear
|
|
channels directly, without applying the sRGB transfer curve. Missing primaries
|
|
and all other primaries refuse illumination; default Radiance RGB is not silently
|
|
relabeled sRGB. Supporting other primaries requires a separately validated gamut
|
|
and white-point conversion. No clipping or invented conversion is used here.
|
|
|
|
## CPU consumer and remaining qualification
|
|
|
|
At the original source handoff, the separately qualified RT2 source was not an
|
|
executed validation result for this module. Integration required real prerequisite
|
|
history or a recorded source overlay, without copied build outputs. Subsequent
|
|
combined CPU renderer checks have executed for environment sampling and the
|
|
actual image consumer; current combined workflow/native gates remain separate.
|
|
|
|
1. Capture the admitted existing HDR source and preserve its original encoded allocation.
|
|
Include encoded/decoded retained capacities, request clones and state in the
|
|
existing 384 MiB job and 512 MiB shared admission. Capture metadata keeps its
|
|
Record-owned lease after frame eviction. Refuse unsupported primaries before publication.
|
|
2. Incremental preparation calls the SAME cumulative job work budget and cancel
|
|
token. The implemented owned adapter moves `EnvironmentInput` through host work
|
|
into one existing `HdrDecodeTask`. The image task owns its completed `DecodedHdr`
|
|
and creates short-lived borrowed views, without a self-referential borrow or a
|
|
second decoded copy. Decoding validates corrected texels incrementally; internal
|
|
views check shape and capacity without rescanning every texel for each sample.
|
|
Renderer decode/ownership/cancellation checks have executed; native visual acceptance remains pending.
|
|
3. At an opaque hit, each environment direct sample creates one positive-minimum
|
|
secondary visibility ray from the shared geometric offset. Reuse the existing
|
|
resumable traversal cursor, charging every sample and traversal unit. Add visible
|
|
estimates in linear space and divide by environment sample count once.
|
|
4. Primary misses remain equal to the requested display background. The
|
|
`radiance_linear_srgb` API is available for later secondary-miss transport;
|
|
reflection continuation is not connected in this consumer. Combining environment
|
|
next-event estimates and rough-specular paths that miss requires matched MIS
|
|
or a documented partition of the two terms; until implemented, refuse that
|
|
combination. Do not count the same environment specular energy twice.
|
|
5. Add environment illumination to existing direct lights without adding another
|
|
ambient term. Exposure, Reinhard and sRGB transfer remain a single final step.
|
|
Image/task/host cancellation must publish no partial successful frame.
|
|
|
|
Original analytic tests generate RGBE bytes at runtime: constant map and PDF,
|
|
single bright cell solid angle, black map, axes/rotation/seam/poles, cancellation
|
|
and shared-budget failure, decoder corrections, unsupported primaries, hostile
|
|
options/directions and an independent white-conductor hemispherical integral.
|
|
The renderer analytic/input cases have executed. Engine source-removal and
|
|
metadata contracts still need current combined qualification. This sampling
|
|
helper itself adds no external assets, dependencies or persistence fields.
|
|
|
|
Mathematical references only; no code or figures copied:
|
|
[PBRT, Infinite Area Lights](https://pbr-book.org/4ed/Light_Sources/Infinite_Area_Lights)
|
|
for radiance and solid-angle estimators (its image mapping is different), and
|
|
[W3C CSS Color 4, sRGB](https://www.w3.org/TR/css-color-4/#predefined-sRGB)
|
|
for the sRGB/D65 primary coordinates and the distinction from encoded sRGB.
|
|
|
|
## Opt-in request
|
|
|
|
`render.preflight` / `render.start` accept an `environment` object alongside
|
|
`integrator:"raytrace"`, for example:
|
|
|
|
```json
|
|
{"integrator":"raytrace","raytrace":{"lights":[]},"environment":{"path":"original-srgb.hdr","rotation_radians":0,"intensity":1,"samples":64}}
|
|
```
|
|
|
|
The input path uses the existing scoped, bounded VFS reader and `HdrSource`.
|
|
The captured source is passed separately to `CpuHost::submit_with_environment`,
|
|
never serialized or cloned into job status. A separate fixed-size `EnvironmentInfo`
|
|
records the SHA-256 digest, numerical header, controls and explicit colour policy in
|
|
preflight and status, without the source path or pixels. Encoded capacity, exact decoded storage,
|
|
scanline storage and bounded state are added before the shared reservation;
|
|
allocators that exceed admitted scanline/decoded capacities refuse. Direct-light
|
|
visibility uses the existing positive-minimum ray and resumable cursor. Primary
|
|
misses retain the exact requested background. Samples use deterministic z/phi
|
|
stratum centres (one sample uses a fixed interior point); finite-count quadrature
|
|
can be biased and is not a convergence or unbiased-rendering claim.
|
|
|
|
The standalone HDR checkpoint has no reflection continuation. This isolated
|
|
combined source connects secondary environment misses and explicitly selected
|
|
metallic rough reflectors or ideal mirrors; see
|
|
[the integration contract](render-hdr-reflections-integration.md). Mixed/diffuse
|
|
rough HDR combinations and unknown optics fields refuse on that legacy route.
|
|
This direct/reflection estimator itself adds no MIS or texture consumer. Saved
|
|
CPU HDR references use the existing [resource contract](render-hdr-resources.md).
|
|
Optional [opaque path lighting](render-cpu-path.md) adds matched light/BSDF MIS and
|
|
BSDF-sampled mesh emission; certified dielectric transport remains a separate
|
|
CPU route. These do not establish mixed glass/GI or general material-map support.
|
|
|
|
Seven consumer source regressions complement the nine analytic/input regressions:
|
|
an image-task PNG oracle and deterministic/background checks, decode/visibility
|
|
cancellation and work exhaustion, native captured-source ownership, four-unit
|
|
quanta, all traversal-to-shading transitions, engine rendering after source-file
|
|
removal compared with unlit geometry, and capture-metadata lease release after
|
|
PNG eviction. Renderer cases have executed; current combined engine contract and native workflow qualification remain separate.
|
|
|
|
Consumer review repairs: environment cursor continuation charges traversal without
|
|
an additional shading debit; each pixel quantum remains at most four shared work
|
|
units. Both request resolvers require `Hdri` when a source is captured. Only the
|
|
native feature-on raytrace descriptor advertises this narrow environment path.
|
|
Preflight and job status retain fixed-size SHA-256 bytes, bounded header numbers,
|
|
controls and explicit colour policy; neither the input path nor image bytes are
|
|
retained there. Fixed metadata is charged to the Record-owned lease independently
|
|
of the PNG, while captured image storage stays under the work lease. Preflight
|
|
includes retained request metadata in its combined per-job estimate. A regression
|
|
withdraws the actual HDR file and compares lit geometry against the same unlit job.
|
|
The renderer ownership and bounded-work cases have executed; the engine file-removal regression still needs current combined qualification.
|