mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 20:02:16 +00:00
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.
|