@photivra/engine 2.16.0 → 2.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +104 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/THIRD_PARTY.md +24 -0
- package/dist/camera/lens-projection.d.ts +5 -0
- package/dist/camera/lens-projection.js +10 -0
- package/dist/camera/lens-projection.js.map +1 -1
- package/dist/camera/sensor-equivalence.d.ts +156 -0
- package/dist/camera/sensor-equivalence.js +208 -0
- package/dist/camera/sensor-equivalence.js.map +1 -0
- package/dist/capture/native-environment-tabulated.d.ts +5 -0
- package/dist/capture/native-environment-tabulated.js +1 -1
- package/dist/capture/native-environment-tabulated.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/generic-lens-catalogue.d.ts +227 -0
- package/dist/equipment/generic-lens-catalogue.js +243 -0
- package/dist/equipment/generic-lens-catalogue.js.map +1 -0
- package/dist/equipment/ideal-lens.d.ts +25 -0
- package/dist/equipment/ideal-lens.js +21 -0
- package/dist/equipment/ideal-lens.js.map +1 -0
- package/dist/facade/catalogue-lens-signal.d.ts +94 -0
- package/dist/facade/catalogue-lens-signal.js +362 -0
- package/dist/facade/catalogue-lens-signal.js.map +1 -0
- package/dist/facade/defocus-bokeh-zones.d.ts +33 -0
- package/dist/facade/defocus-bokeh-zones.js +53 -0
- package/dist/facade/defocus-bokeh-zones.js.map +1 -0
- package/dist/facade/defocus-image-space-provider.d.ts +9 -0
- package/dist/facade/defocus-image-space-provider.js +101 -9
- package/dist/facade/defocus-image-space-provider.js.map +1 -1
- package/dist/facade/diffraction-provider.d.ts +29 -0
- package/dist/facade/diffraction-provider.js +117 -11
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view-gpu-session.js +4 -0
- package/dist/facade/display-view-gpu-session.js.map +1 -1
- package/dist/facade/display-view-gpu.d.ts +10 -0
- package/dist/facade/display-view-gpu.js.map +1 -1
- package/dist/facade/display-view-lens-signal.d.ts +61 -0
- package/dist/facade/display-view-lens-signal.js +502 -0
- package/dist/facade/display-view-lens-signal.js.map +1 -0
- package/dist/facade/expected-signal-setup.d.ts +15 -0
- package/dist/facade/expected-signal-setup.js +19 -2
- package/dist/facade/expected-signal-setup.js.map +1 -1
- package/dist/facade/expected-signal.d.ts +13 -0
- package/dist/facade/expected-signal.js +155 -1
- package/dist/facade/expected-signal.js.map +1 -1
- package/dist/facade/generic-lens-capture.d.ts +7 -0
- package/dist/facade/generic-lens-capture.js +9 -0
- package/dist/facade/generic-lens-capture.js.map +1 -0
- package/dist/facade/large-defocus-lattice.d.ts +39 -0
- package/dist/facade/large-defocus-lattice.js +64 -0
- package/dist/facade/large-defocus-lattice.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +5 -0
- package/dist/facade/scene-radiance.js +5 -2
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +67 -7
- package/dist/facade/simulate-capture.js +400 -64
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +23 -17
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +0 -9
- package/dist/gpu/display-view-quality-gpu.js +6 -0
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +2 -0
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/optics/defocus-bokeh-kernel.d.ts +207 -0
- package/dist/optics/defocus-bokeh-kernel.js +380 -0
- package/dist/optics/defocus-bokeh-kernel.js.map +1 -0
- package/dist/optics/defocus-disc-kernel.d.ts +41 -19
- package/dist/optics/defocus-disc-kernel.js +44 -23
- package/dist/optics/defocus-disc-kernel.js.map +1 -1
- package/dist/optics/generic-lens-psf.d.ts +68 -0
- package/dist/optics/generic-lens-psf.js +337 -0
- package/dist/optics/generic-lens-psf.js.map +1 -0
- package/dist/optics/illumination-vignetting.d.ts +6 -0
- package/dist/optics/illumination-vignetting.js +24 -7
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/sensor-environment-query.d.ts +6 -0
- package/dist/optics/sensor-environment-query.js +13 -6
- package/dist/optics/sensor-environment-query.js.map +1 -1
- package/dist/optics/site-kernel-runs.d.ts +77 -0
- package/dist/optics/site-kernel-runs.js +200 -0
- package/dist/optics/site-kernel-runs.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +24 -0
- package/dist/output/generic-lens-corrections.js +51 -0
- package/dist/output/generic-lens-corrections.js.map +1 -0
- package/docs/AGENT_GUIDE.md +4 -0
- package/docs/API_REFERENCE.md +77 -1
- package/docs/QUICK_START.md +305 -17
- package/docs/USAGE.md +98 -5
- package/docs/api/camera-sensor-equivalence.md +209 -0
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-lens-catalogue.md +281 -0
- package/docs/api/equipment-ideal-lens.md +26 -0
- package/docs/api/exports.json +202 -2
- package/docs/api/facade-simulate-capture.md +48 -4
- package/docs/api/optics-defocus-bokeh-kernel.md +145 -0
- package/docs/api/optics-defocus-disc-kernel.md +22 -15
- package/docs/api/optics-sensor-environment-query.md +6 -0
- package/docs/api/output-generic-lens-corrections.md +39 -0
- package/llms.txt +3 -0
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* `lens.defocus` with a cat's eye (#553): the field zones of the capture's field-varying defocus kernel. The native raster is
|
|
4
|
+
* cut into square zones (`fieldZonesAcrossLongSide` across its long side); each zone's kernel is the shaped kernel of the
|
|
5
|
+
* field point at the zone's centre (`createDefocusBokehSiteKernel`), padded to the axis kernel's radius (the cat's eye only
|
|
6
|
+
* removes light from the opening, so no zone's blur reaches further than the unclipped one). The gather
|
|
7
|
+
* (`createZonedGather`) gives every site its zone's kernel: a piecewise-constant approximation of the space-variant blur,
|
|
8
|
+
* whose step between neighbouring zones is reported (the largest change of the open-area ratio). Internal.
|
|
9
|
+
*/
|
|
10
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
11
|
+
import { openPupilAreaRatio } from "../optics/defocus-bokeh-kernel.js";
|
|
12
|
+
/**
|
|
13
|
+
* Plans the zones. `fieldOf(x, y)` is the field tangent of native point (x, y) in sites from the raster's top-left corner;
|
|
14
|
+
* `kernelAt(field)` builds a zone's kernel (its radius at most `radius`). Kernels are built on first use by the gather.
|
|
15
|
+
*/
|
|
16
|
+
export function planDefocusBokehZones(input) {
|
|
17
|
+
const { options, nativeWidth: W, nativeHeight: H, radius: R } = input;
|
|
18
|
+
const across = options.catsEye.fieldZonesAcrossLongSide, size = Math.ceil(Math.max(W, H) / across);
|
|
19
|
+
const columns = Math.ceil(W / size), rows = Math.ceil(H / size), fields = [], ratios = [];
|
|
20
|
+
for (let zy = 0; zy < rows; zy++)
|
|
21
|
+
for (let zx = 0; zx < columns; zx++) {
|
|
22
|
+
const field = input.fieldOf((zx * size + Math.min(W, (zx + 1) * size)) / 2, (zy * size + Math.min(H, (zy + 1) * size)) / 2);
|
|
23
|
+
fields.push(field);
|
|
24
|
+
ratios.push(openPupilAreaRatio(options, input.fNumber, input.focalLengthMm, field));
|
|
25
|
+
}
|
|
26
|
+
let minimum = Infinity, step = 0;
|
|
27
|
+
for (let zy = 0; zy < rows; zy++)
|
|
28
|
+
for (let zx = 0; zx < columns; zx++) {
|
|
29
|
+
const r = ratios[zy * columns + zx];
|
|
30
|
+
minimum = Math.min(minimum, r);
|
|
31
|
+
if (zx + 1 < columns)
|
|
32
|
+
step = Math.max(step, Math.abs(r - ratios[zy * columns + zx + 1]));
|
|
33
|
+
if (zy + 1 < rows)
|
|
34
|
+
step = Math.max(step, Math.abs(r - ratios[(zy + 1) * columns + zx]));
|
|
35
|
+
}
|
|
36
|
+
const width = 2 * R + 1;
|
|
37
|
+
return {
|
|
38
|
+
fields, minimumOpenAreaRatio: minimum, largestAdjacentOpenAreaRatioChange: step,
|
|
39
|
+
zones: { size, columns, rows, kernelOf(zone) {
|
|
40
|
+
const k = input.kernelAt(fields[zone]);
|
|
41
|
+
if (k.radius === R)
|
|
42
|
+
return k.weights;
|
|
43
|
+
if (k.radius > R)
|
|
44
|
+
throw new InvalidConfigurationError("lens.defocus: a cat's-eye zone kernel reaches beyond the unclipped kernel's radius.");
|
|
45
|
+
const padded = new Float64Array(width * width), offset = R - k.radius;
|
|
46
|
+
for (let j = 0; j < k.width; j++)
|
|
47
|
+
for (let i = 0; i < k.width; i++)
|
|
48
|
+
padded[(j + offset) * width + i + offset] = k.weights[j * k.width + i];
|
|
49
|
+
return padded;
|
|
50
|
+
} }
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=defocus-bokeh-zones.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defocus-bokeh-zones.js","sourceRoot":"","sources":["../../src/facade/defocus-bokeh-zones.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * `lens.defocus` with a cat's eye (#553): the field zones of the capture's field-varying defocus kernel. The native raster is\n * cut into square zones (`fieldZonesAcrossLongSide` across its long side); each zone's kernel is the shaped kernel of the\n * field point at the zone's centre (`createDefocusBokehSiteKernel`), padded to the axis kernel's radius (the cat's eye only\n * removes light from the opening, so no zone's blur reaches further than the unclipped one). The gather\n * (`createZonedGather`) gives every site its zone's kernel: a piecewise-constant approximation of the space-variant blur,\n * whose step between neighbouring zones is reported (the largest change of the open-area ratio). Internal.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport type { SiteKernelFieldZones } from \"./diffraction-provider.js\";\nimport { openPupilAreaRatio, type DefocusBokehSiteKernel, type ResolvedDefocusBokehOptions } from \"../optics/defocus-bokeh-kernel.js\";\n\nexport interface DefocusBokehZonePlan {\n zones: SiteKernelFieldZones;\n /** Field tangent of each zone centre (output-image axes, +Y up), row-major. */\n fields: readonly { x: number; y: number }[];\n /** Smallest open-area ratio over the zone centres, and the largest change between two zones sharing an edge. */\n minimumOpenAreaRatio: number;\n largestAdjacentOpenAreaRatioChange: number;\n}\n\n/**\n * Plans the zones. `fieldOf(x, y)` is the field tangent of native point (x, y) in sites from the raster's top-left corner;\n * `kernelAt(field)` builds a zone's kernel (its radius at most `radius`). Kernels are built on first use by the gather.\n */\nexport function planDefocusBokehZones(input: { options: ResolvedDefocusBokehOptions; nativeWidth: number; nativeHeight: number; radius: number;\n fNumber: number; focalLengthMm: number; fieldOf: (x: number, y: number) => { x: number; y: number }; kernelAt: (field: { x: number; y: number }) => DefocusBokehSiteKernel }): DefocusBokehZonePlan {\n const { options, nativeWidth: W, nativeHeight: H, radius: R } = input;\n const across = options.catsEye!.fieldZonesAcrossLongSide, size = Math.ceil(Math.max(W, H) / across);\n const columns = Math.ceil(W / size), rows = Math.ceil(H / size), fields: { x: number; y: number }[] = [], ratios: number[] = [];\n for (let zy = 0; zy < rows; zy++) for (let zx = 0; zx < columns; zx++) {\n const field = input.fieldOf((zx * size + Math.min(W, (zx + 1) * size)) / 2, (zy * size + Math.min(H, (zy + 1) * size)) / 2);\n fields.push(field);\n ratios.push(openPupilAreaRatio(options, input.fNumber, input.focalLengthMm, field));\n }\n let minimum = Infinity, step = 0;\n for (let zy = 0; zy < rows; zy++) for (let zx = 0; zx < columns; zx++) {\n const r = ratios[zy * columns + zx]!;\n minimum = Math.min(minimum, r);\n if (zx + 1 < columns) step = Math.max(step, Math.abs(r - ratios[zy * columns + zx + 1]!));\n if (zy + 1 < rows) step = Math.max(step, Math.abs(r - ratios[(zy + 1) * columns + zx]!));\n }\n const width = 2 * R + 1;\n return {\n fields, minimumOpenAreaRatio: minimum, largestAdjacentOpenAreaRatioChange: step,\n zones: { size, columns, rows, kernelOf(zone: number): Float64Array {\n const k = input.kernelAt(fields[zone]!);\n if (k.radius === R) return k.weights;\n if (k.radius > R) throw new InvalidConfigurationError(\"lens.defocus: a cat's-eye zone kernel reaches beyond the unclipped kernel's radius.\");\n const padded = new Float64Array(width * width), offset = R - k.radius;\n for (let j = 0; j < k.width; j++) for (let i = 0; i < k.width; i++) padded[(j + offset) * width + i + offset] = k.weights[j * k.width + i]!;\n return padded;\n } }\n };\n}\n"]}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type CameraAngularVelocityRadPerSec } from "../motion/camera-rotation.js";
|
|
2
2
|
import { type IlluminationVignettingProfile } from "../optics/illumination-vignetting.js";
|
|
3
3
|
import { type PreparedEnvironmentLensFieldMapping } from "../optics/sensor-environment-query.js";
|
|
4
|
+
import { type SiteKernelFieldZones } from "./diffraction-provider.js";
|
|
4
5
|
import type { PlanarSceneRadianceProvider } from "./scene-radiance.js";
|
|
6
|
+
import { type LargeDefocusKernel } from "./large-defocus-lattice.js";
|
|
5
7
|
/** The camera geometry the environment uses for each site query (the same options as the site inputs). */
|
|
6
8
|
export interface DefocusImageSpaceGeometry {
|
|
7
9
|
focalLengthMm: number;
|
|
@@ -67,6 +69,13 @@ export interface DefocusImageSpaceProviderInput {
|
|
|
67
69
|
timesPerBand?: number;
|
|
68
70
|
/** Called with the duration in ms of each band convolution (diagnostics only). */
|
|
69
71
|
onConvolution?: (milliseconds: number) => void;
|
|
72
|
+
/**
|
|
73
|
+
* #564: a defocus kernel above the direct radius, convolved by runs in fixed tiles (`large-defocus-lattice.ts`), with each
|
|
74
|
+
* node's diffraction kernel after it; used instead of `siteKernels` (`kernelRadius` is then unused).
|
|
75
|
+
*/
|
|
76
|
+
largeKernel?: LargeDefocusKernel;
|
|
77
|
+
/** #553: a field-varying kernel by zones (the cat's eye of lens.defocus), gathered instead of `siteKernels`, the same at every node. */
|
|
78
|
+
fieldZones?: SiteKernelFieldZones;
|
|
70
79
|
}
|
|
71
80
|
/** Internal (not exported from the package): the base provider with the defocus disc applied in image space (#548). */
|
|
72
81
|
export declare function createDefocusImageSpaceProvider(input: DefocusImageSpaceProviderInput): PlanarSceneRadianceProvider;
|
|
@@ -37,14 +37,17 @@
|
|
|
37
37
|
* What is approximate is the disc itself (`lens.defocus` labels it; the facade records the field-variation bounds of
|
|
38
38
|
* each combination), not this evaluation of it.
|
|
39
39
|
*/
|
|
40
|
+
// #564: a defocus kernel above 64 sites (`largeKernel`) takes the run lattice of large-defocus-lattice.ts instead of the bands:
|
|
41
|
+
// the samples F·L at the same lattice points, convolved by runs in fixed tiles, then divided by each queried point's own F.
|
|
40
42
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
41
43
|
import { hypot3 } from "../core/portable-math.js";
|
|
42
44
|
import { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from "../core/internal-radiance-evaluator.js";
|
|
43
|
-
import { lensProjectionDirectionValue, lensProjectionImagePointValue } from "../camera/lens-projection.js";
|
|
45
|
+
import { insideRadialImageCircle, lensProjectionDirectionValue, lensProjectionImagePointValue } from "../camera/lens-projection.js";
|
|
44
46
|
import { applyPhysicalCameraRotation, resolveProjectionDistanceMm } from "../motion/camera-rotation.js";
|
|
45
|
-
import {
|
|
47
|
+
import { prepareIlluminationVignettingThroughput } from "../optics/illumination-vignetting.js";
|
|
46
48
|
import { distortedImagePoint, undistortedImagePoint } from "../optics/sensor-environment-query.js";
|
|
47
|
-
import { checkedSiteKernel, gatherInterior, kernelTaps } from "./diffraction-provider.js";
|
|
49
|
+
import { checkedSiteKernel, createZonedGather, gatherInterior, kernelTaps } from "./diffraction-provider.js";
|
|
50
|
+
import { LARGE_DEFOCUS_CACHE_BYTES, createLargeDefocusNodeLattice } from "./large-defocus-lattice.js";
|
|
48
51
|
/** Rows of native sites per band; bands kept per time. Banding changes memory only, never values. */
|
|
49
52
|
const BAND_ROWS = 32;
|
|
50
53
|
const CACHED_BANDS = 2;
|
|
@@ -55,7 +58,11 @@ export function prepareDefocusImageSpaceGeometry(geometry) {
|
|
|
55
58
|
// The projection scale: the thin-lens image distance at the finite focus, for every projection model (the environment's).
|
|
56
59
|
const pd = resolveProjectionDistanceMm(focalLengthMm, focusDistanceM).projectionDistanceMm;
|
|
57
60
|
const model = lensMapping?.mapping.projectionModel ?? "rectilinear";
|
|
61
|
+
// #569: with "backward-ray" (catalogue fisheyes), a point outside the image circle looks straight back, as the environment's mapped query does.
|
|
62
|
+
const backward = lensMapping?.mapping.outsideImageCircle === "backward-ray";
|
|
58
63
|
const timeDependent = omega.pitch !== 0 || omega.yaw !== 0 || omega.roll !== 0;
|
|
64
|
+
// calculateIlluminationVignetting's throughput with the profile validated once (#563: the same numbers, without a result envelope per point).
|
|
65
|
+
const throughputAt = vignetting ? prepareIlluminationVignettingThroughput(vignetting) : undefined;
|
|
59
66
|
const displacement = (t) => timeDependent ? { pitch: omega.pitch * t, yaw: omega.yaw * t, roll: omega.roll * t } : { pitch: 0, yaw: 0, roll: 0 };
|
|
60
67
|
// The reference-to-camera rotation at the last time asked, as a matrix (its columns: the rotated basis vectors), so a lattice
|
|
61
68
|
// lookup costs no trigonometry; the rotation is linear, so this equals rotating the vector, up to rounding.
|
|
@@ -84,13 +91,14 @@ export function prepareDefocusImageSpaceGeometry(geometry) {
|
|
|
84
91
|
lz = pd;
|
|
85
92
|
}
|
|
86
93
|
else {
|
|
87
|
-
const reference = applyPhysicalCameraRotation(
|
|
94
|
+
const reference = applyPhysicalCameraRotation(backward && !insideRadialImageCircle(model, pd, Math.hypot(ideal.x, ideal.y)) ? { x: 0, y: 0, z: -1 } :
|
|
95
|
+
lensProjectionDirectionValue(model, pd, ideal.x, ideal.y), displacement(t), "camera-to-reference");
|
|
88
96
|
lx = reference.x;
|
|
89
97
|
ly = reference.y;
|
|
90
98
|
lz = reference.z;
|
|
91
99
|
}
|
|
92
100
|
const length = hypot3(lx, ly, lz);
|
|
93
|
-
const throughput =
|
|
101
|
+
const throughput = throughputAt ? throughputAt(image) : 1;
|
|
94
102
|
return { x: lx / length, y: ly / length, z: lz / length, factor: throughput * distortionAreaFactor };
|
|
95
103
|
},
|
|
96
104
|
sensorPointOf(look, t) {
|
|
@@ -134,9 +142,11 @@ export function createDefocusImageSpaceProvider(input) {
|
|
|
134
142
|
if (!(lx0 < lx1 && ly0 < ly1))
|
|
135
143
|
throw new InvalidConfigurationError("Defocus window must overlap the native raster.");
|
|
136
144
|
const NW = lx1 - lx0, gridWidth = NW + 2 * R;
|
|
137
|
-
const
|
|
145
|
+
const large = input.largeKernel;
|
|
146
|
+
const kernels = large ? [] : wavelengthsNm.map((nm) => checkedSiteKernel(input.siteKernels(nm), R));
|
|
138
147
|
const taps = kernels.map((kernel) => kernelTaps(kernel, R, gridWidth));
|
|
139
|
-
const
|
|
148
|
+
const zonedGather = input.fieldZones ? createZonedGather(input.fieldZones, R, gridWidth, W, H, M) : undefined;
|
|
149
|
+
const sharedKernel = !large && (zonedGather !== undefined || kernels.every((kernel) => kernel === kernels[0]));
|
|
140
150
|
const scale = input.metresPerFrameUnit, distance = input.distanceM;
|
|
141
151
|
const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);
|
|
142
152
|
const now = () => globalThis.performance?.now() ?? Date.now();
|
|
@@ -200,7 +210,7 @@ export function createDefocusImageSpaceProvider(input) {
|
|
|
200
210
|
for (let k = 0; k < size; k++)
|
|
201
211
|
if (material[k] === m)
|
|
202
212
|
samples[k] = factor[k];
|
|
203
|
-
return gatherInterior(samples, taps[0], gridWidth, NW, rows, R);
|
|
213
|
+
return zonedGather ? zonedGather(samples, lx0, y0, NW, rows) : gatherInterior(samples, taps[0], gridWidth, NW, rows, R);
|
|
204
214
|
});
|
|
205
215
|
return wavelengthsNm.map((nm) => {
|
|
206
216
|
const radiance = present.map((m) => materialRadiance(m, nm)), out = new Float64Array(rows * NW);
|
|
@@ -234,7 +244,7 @@ export function createDefocusImageSpaceProvider(input) {
|
|
|
234
244
|
else
|
|
235
245
|
for (let k = 0; k < size; k++)
|
|
236
246
|
samples[k] = factor[k] * base.radianceAt(u[k], v[k], nm);
|
|
237
|
-
const gathered = gatherInterior(samples, taps[w], gridWidth, NW, rows, R);
|
|
247
|
+
const gathered = zonedGather ? zonedGather(samples, lx0, y0, NW, rows) : gatherInterior(samples, taps[w], gridWidth, NW, rows, R);
|
|
238
248
|
for (let k = 0; k < gathered.length; k++)
|
|
239
249
|
gathered[k] = gathered[k] / own[k];
|
|
240
250
|
return gathered;
|
|
@@ -269,8 +279,90 @@ export function createDefocusImageSpaceProvider(input) {
|
|
|
269
279
|
if (w === undefined)
|
|
270
280
|
throw new InvalidConfigurationError("Defocus query is off the sensor site lattice; the image-space convolution does not apply.");
|
|
271
281
|
const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;
|
|
282
|
+
if (large)
|
|
283
|
+
return largeValue(s, t, w, li, lj);
|
|
272
284
|
return band(Math.floor((lj - ly0) / BAND_ROWS), t)[s][w][((lj - ly0) % BAND_ROWS) * NW + li - lx0];
|
|
273
285
|
}
|
|
286
|
+
// #564: one run lattice per (time, shift) of the samples F·L at the lattice points, and the own field factors F by tile, so a
|
|
287
|
+
// query is answered with (K ⊛ D ⊛ F·L) / F as on the band path.
|
|
288
|
+
const largeLattices = new Map();
|
|
289
|
+
const largeLatticeCount = shifts.length * Math.max(1, input.timesPerBand ?? 1);
|
|
290
|
+
// Lattice points at most `reach` beyond the lattice feed queried values: the defocus kernel's radius plus the diffraction kernel's.
|
|
291
|
+
const reach = large ? large.runs.radius + (large.diffraction ? large.diffraction.radius : 0) : 0;
|
|
292
|
+
function largeValue(s, time, w, li, lj) {
|
|
293
|
+
const key = time + ":" + s;
|
|
294
|
+
let entry = largeLattices.get(key);
|
|
295
|
+
if (!entry) {
|
|
296
|
+
const shift = shifts[s];
|
|
297
|
+
const lattice = createLargeDefocusNodeLattice({ kernel: large, wavelengthsNm, capacityBytes: LARGE_DEFOCUS_CACHE_BYTES / largeLatticeCount, ...(input.onConvolution ? { onTile: input.onConvolution } : {}),
|
|
298
|
+
source: (x0, y0, width, height) => {
|
|
299
|
+
const size = width * height, factor = new Float64Array(size), u = new Float64Array(size), v = new Float64Array(size);
|
|
300
|
+
const material = materialAt && materialRadiance ? new Int32Array(size) : undefined, beyond = new Uint8Array(size);
|
|
301
|
+
for (let y = 0; y < height; y++) {
|
|
302
|
+
const yMm = yMmOf(y0 + y, shift);
|
|
303
|
+
for (let x = 0; x < width; x++) {
|
|
304
|
+
const k = y * width + x;
|
|
305
|
+
// A fixed tile's source reaches past the lattice: points beyond its reach feed no queried value, so they are 0 and never
|
|
306
|
+
// mapped (the lens profiles are checked only up to the reach).
|
|
307
|
+
if (x0 + x < -reach || x0 + x >= LW + reach || y0 + y < -reach || y0 + y >= LH + reach) {
|
|
308
|
+
beyond[k] = 1;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
const look = geometry.lookOf(xMmOf(x0 + x, shift), yMm, time);
|
|
312
|
+
if (!(look.z > 0))
|
|
313
|
+
throw new InvalidConfigurationError("lens.defocus: a lattice point's ray does not point toward the scene plane.");
|
|
314
|
+
const t = distance / look.z;
|
|
315
|
+
factor[k] = look.factor;
|
|
316
|
+
u[k] = look.x * t / scale;
|
|
317
|
+
v[k] = look.y * t / scale;
|
|
318
|
+
if (material)
|
|
319
|
+
material[k] = materialAt(u[k], v[k]);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return (node) => {
|
|
323
|
+
const nm = wavelengthsNm[node], samples = new Float64Array(size);
|
|
324
|
+
if (material) {
|
|
325
|
+
const radiance = new Map();
|
|
326
|
+
for (let k = 0; k < size; k++) {
|
|
327
|
+
if (beyond[k])
|
|
328
|
+
continue;
|
|
329
|
+
const m = material[k];
|
|
330
|
+
let value = radiance.get(m);
|
|
331
|
+
if (value === undefined) {
|
|
332
|
+
value = materialRadiance(m, nm);
|
|
333
|
+
radiance.set(m, value);
|
|
334
|
+
}
|
|
335
|
+
samples[k] = factor[k] * value;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
else
|
|
339
|
+
for (let k = 0; k < size; k++)
|
|
340
|
+
if (!beyond[k])
|
|
341
|
+
samples[k] = factor[k] * base.radianceAt(u[k], v[k], nm);
|
|
342
|
+
return samples;
|
|
343
|
+
};
|
|
344
|
+
} });
|
|
345
|
+
entry = { lattice, own: new Map() };
|
|
346
|
+
largeLattices.set(key, entry);
|
|
347
|
+
if (largeLattices.size > largeLatticeCount)
|
|
348
|
+
largeLattices.delete(largeLattices.keys().next().value);
|
|
349
|
+
}
|
|
350
|
+
// The own factor of the lattice point, by 64-point tiles (kept for the request: 8 bytes per lattice point read).
|
|
351
|
+
const T = 64, tx = Math.floor(li / T), ty = Math.floor(lj / T), tileKey = ty * 1048576 + tx;
|
|
352
|
+
let own = entry.own.get(tileKey);
|
|
353
|
+
if (!own) {
|
|
354
|
+
own = new Float64Array(T * T);
|
|
355
|
+
const shift = shifts[s];
|
|
356
|
+
// Only the lattice's own points are queried; the rest of the tile is never read (and may lie beyond the lens profiles).
|
|
357
|
+
for (let y = 0; y < T && ty * T + y < LH; y++) {
|
|
358
|
+
const yMm = yMmOf(ty * T + y, shift);
|
|
359
|
+
for (let x = 0; x < T && tx * T + x < LW; x++)
|
|
360
|
+
own[y * T + x] = geometry.lookOf(xMmOf(tx * T + x, shift), yMm, time).factor;
|
|
361
|
+
}
|
|
362
|
+
entry.own.set(tileKey, own);
|
|
363
|
+
}
|
|
364
|
+
return entry.lattice.valueAt(w, li, lj) / own[(lj - ty * T) * T + li - tx * T];
|
|
365
|
+
}
|
|
274
366
|
function blurredAt(look, time, nm) {
|
|
275
367
|
const t = geometry.timeDependent ? time : 0, key = keyOf(look, t);
|
|
276
368
|
if (key === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defocus-image-space-provider.js","sourceRoot":"","sources":["../../src/facade/defocus-image-space-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * `simulateCapture`'s `lens.defocus` out of focus together with a lens field mapping (`lens.projection`,\n * `lens.distortion`), `lens.vignetting` or camera rotation (#548): the geometric defocus disc applied in image space,\n * on the site lattice of the sensor, instead of on the scene plane.\n *\n * Why the object-space path does not apply. `createDiffractedPlanarProvider` convolves the scene radiance on the plane\n * lattice that the sites see through one linear map (a still, rectilinear, distortion-free camera with the same\n * radiance-to-irradiance factor everywhere). A projection, a distortion or a rotation makes the map from sensor points\n * to plane points non-linear (or time-dependent), and vignetting makes the factor vary over the field, so the disc on\n * the plane is no longer the disc on the sensor.\n *\n * The image-space model. The environment PSF quadrature (`calculateSensorPsfIrradianceQuadrature`, the per-tap path\n * `lens.diffraction` falls back to) defines a sensor-plane PSF K as\n * E(q, λ, t) = Σ_k K(k)·F(s_k)·C·L(D_t(s_k), λ),\n * with s_k = q + k·p the tap source points on the sensor (p the site pitch), D_t the scene ray of a sensor point at\n * time t (inverse distortion, the declared projection, the camera rotation at t), F = T·A the field factor (vignetting\n * throughput T, applied once before the PSF spreads the light, and the distortion area factor A = 1/det J) and C the\n * paraxial radiance-to-irradiance factor π/(4·N_w²), the same everywhere. With K the defocus disc sampled on the site\n * lattice (`createDefocusDiscSiteKernel`), every source point of a site-centre query is another lattice point, so\n * E(q, λ, t) = C·G_t(q, λ), G_t = K ⊛ (F·L∘D_t) sampled on the lattice,\n * the same sum in a different floating-point order. This provider computes G_t once per spectral node and time on the\n * sensor lattice (in row bands, as the diffraction provider does) and answers the query of lattice point q at time t with\n * G_t(q, λ) / F(q); the environment multiplies by F(q)·C again, so each site gets C·G_t(q, λ). For the still,\n * rectilinear, distortion-free camera without vignetting it is the object-space convolution (F = 1 and D linear).\n *\n * The lattices. As in the diffraction provider, a pixel aperture or anti-aliasing spots add query offsets; each distinct\n * fractional offset gets its own shifted lattice of sensor points, and every tap of a query on one lattice is on the same\n * lattice. A query is located on its lattice by mapping its scene ray back to the sensor (camera rotation inverted at the\n * request's time, the forward projection, the forward distortion), within 1e-4 site; a query that lands on no lattice point\n * is refused rather than approximated.\n *\n * Time. With camera rotation each environment temporal midpoint is a still camera, so the disc is applied to that\n * instant's image in that instant's frame: one G_t per distinct request time, cached per band. Without rotation the image\n * does not depend on time and one G is kept. The facade refuses rotation with a rolling shutter (each row's instants differ).\n *\n * What is approximate is the disc itself (`lens.defocus` labels it; the facade records the field-variation bounds of\n * each combination), not this evaluation of it.\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { hypot3 } from \"../core/portable-math.js\";\nimport { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from \"../core/internal-radiance-evaluator.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { lensProjectionDirectionValue, lensProjectionImagePointValue, type LensProjectionModel } from \"../camera/lens-projection.js\";\nimport { applyPhysicalCameraRotation, resolveProjectionDistanceMm, type CameraAngularVelocityRadPerSec } from \"../motion/camera-rotation.js\";\nimport { calculateIlluminationVignetting, type IlluminationVignettingProfile } from \"../optics/illumination-vignetting.js\";\nimport { distortedImagePoint, undistortedImagePoint, type PreparedEnvironmentLensFieldMapping } from \"../optics/sensor-environment-query.js\";\nimport { checkedSiteKernel, gatherInterior, kernelTaps } from \"./diffraction-provider.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\n\n/** Rows of native sites per band; bands kept per time. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 2;\nconst LATTICE_TOLERANCE_SITES = 1e-4;\n\n/** The camera geometry the environment uses for each site query (the same options as the site inputs). */\nexport interface DefocusImageSpaceGeometry {\n focalLengthMm: number;\n focusDistanceM: number;\n angularVelocityRadPerSec: CameraAngularVelocityRadPerSec;\n /** The site inputs' `lensFieldMapping`, prepared; omitted for the ideal rectilinear, distortion-free mapping. */\n lensMapping?: PreparedEnvironmentLensFieldMapping;\n /** The site inputs' radial-illumination-vignetting profile; omitted for unity field throughput. */\n vignetting?: IlluminationVignettingProfile;\n}\n\n/** Internal: the scene ray and field factor of sensor points, and the sensor point of a scene ray, for one geometry. */\nexport interface PreparedDefocusImageSpaceGeometry {\n /**\n * The unit look direction (toward the scene, reference camera axes at exposure start) of native sensor point (x, y) mm\n * (+X right, +Y down) at time t, and its field factor F = T·A (vignetting throughput × distortion area factor).\n */\n lookOf(xMm: number, yMm: number, timeSeconds: number): { x: number; y: number; z: number; factor: number };\n /** The native sensor point (mm, +Y down) whose scene ray at time t is the look direction; undefined outside the mapping. */\n sensorPointOf(look: { x: number; y: number; z: number }, timeSeconds: number): { x: number; y: number } | undefined;\n /** True with camera rotation: the ray of a sensor point depends on time. */\n timeDependent: boolean;\n}\n\n/** Internal: prepares {@link PreparedDefocusImageSpaceGeometry} with the environment's own conventions and arithmetic. */\nexport function prepareDefocusImageSpaceGeometry(geometry: DefocusImageSpaceGeometry): PreparedDefocusImageSpaceGeometry {\n const { focalLengthMm, focusDistanceM, angularVelocityRadPerSec: omega, lensMapping, vignetting } = geometry;\n // The projection scale: the thin-lens image distance at the finite focus, for every projection model (the environment's).\n const pd = resolveProjectionDistanceMm(focalLengthMm, focusDistanceM).projectionDistanceMm;\n const model: LensProjectionModel = lensMapping?.mapping.projectionModel ?? \"rectilinear\";\n const timeDependent = omega.pitch !== 0 || omega.yaw !== 0 || omega.roll !== 0;\n const displacement = (t: number): { pitch: number; yaw: number; roll: number } =>\n timeDependent ? { pitch: omega.pitch * t, yaw: omega.yaw * t, roll: omega.roll * t } : { pitch: 0, yaw: 0, roll: 0 };\n // The reference-to-camera rotation at the last time asked, as a matrix (its columns: the rotated basis vectors), so a lattice\n // lookup costs no trigonometry; the rotation is linear, so this equals rotating the vector, up to rounding.\n let matrixTime = NaN, m: number[] = [];\n const toCamera = (v: { x: number; y: number; z: number }, t: number): { x: number; y: number; z: number } => {\n if (t !== matrixTime) {\n const d = displacement(t), ex = applyPhysicalCameraRotation({ x: 1, y: 0, z: 0 }, d, \"reference-to-camera\"),\n ey = applyPhysicalCameraRotation({ x: 0, y: 1, z: 0 }, d, \"reference-to-camera\"), ez = applyPhysicalCameraRotation({ x: 0, y: 0, z: 1 }, d, \"reference-to-camera\");\n m = [ex.x, ey.x, ez.x, ex.y, ey.y, ez.y, ex.z, ey.z, ez.z];\n matrixTime = t;\n }\n return { x: m[0]! * v.x + m[1]! * v.y + m[2]! * v.z, y: m[3]! * v.x + m[4]! * v.y + m[5]! * v.z, z: m[6]! * v.x + m[7]! * v.y + m[8]! * v.z };\n };\n return {\n timeDependent,\n lookOf(xMm, yMm, t): { x: number; y: number; z: number; factor: number } {\n const image = { x: xMm, y: -yMm };\n const { ideal, distortionAreaFactor } = lensMapping ? undistortedImagePoint(lensMapping, image) : { ideal: image, distortionAreaFactor: 1 };\n let lx: number, ly: number, lz: number;\n if (model === \"rectilinear\") {\n // calculateInverseCameraRotationImageMapping: the captured ray (x/pd, y/pd, 1) in reference axes, projected at pd.\n const reference = applyPhysicalCameraRotation({ x: ideal.x / pd, y: ideal.y / pd, z: 1 }, displacement(t), \"camera-to-reference\");\n if (!(reference.z > 0)) throw new InvalidConfigurationError(\"lens.defocus: a lattice point's ray points to or behind the reference camera plane.\");\n lx = pd * (reference.x / reference.z); ly = pd * (reference.y / reference.z); lz = pd;\n } else {\n const reference = applyPhysicalCameraRotation(lensProjectionDirectionValue(model, pd, ideal.x, ideal.y), displacement(t), \"camera-to-reference\");\n lx = reference.x; ly = reference.y; lz = reference.z;\n }\n const length = hypot3(lx, ly, lz);\n const throughput = vignetting ? calculateIlluminationVignetting({ imagePointMm: image, profile: vignetting }).value.linearThroughputFactor : 1;\n return { x: lx / length, y: ly / length, z: lz / length, factor: throughput * distortionAreaFactor };\n },\n sensorPointOf(look, t): { x: number; y: number } | undefined {\n try {\n const c = timeDependent ? toCamera(look, t) : look;\n let ideal: { x: number; y: number };\n if (model === \"rectilinear\") {\n if (!(c.z > 0)) return undefined;\n ideal = { x: pd * (c.x / c.z), y: pd * (c.y / c.z) };\n } else ideal = lensProjectionImagePointValue(model, pd, c.x, c.y, c.z).imagePointMm;\n const image = lensMapping ? distortedImagePoint(lensMapping, ideal).pointMm : ideal;\n return Number.isFinite(image.x) && Number.isFinite(image.y) ? { x: image.x, y: -image.y } : undefined;\n } catch {\n return undefined;\n }\n }\n };\n}\n\nexport interface DefocusImageSpaceProviderInput {\n base: PlanarSceneRadianceProvider;\n geometry: PreparedDefocusImageSpaceGeometry;\n /** Each spectral node's kernel on the site lattice, (2·kernelRadius + 1)² taps, row-major (the disc, or diffraction ⊛ disc). */\n siteKernels: (wavelengthNm: number) => Float64Array;\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider (plane distance and frame-unit scale), to find the plane point of a ray as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /** Offsets of the query points from the site centres, in sites (+x right, +y down). Default: one zero offset. */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /** Region renders: the native sites that will be queried. Values are bit-identical to the whole render's. Default: the whole raster. */\n window?: { x: number; y: number; width: number; height: number };\n /** Most distinct request times kept per band (the temporal sample count). Default 1. */\n timesPerBand?: number;\n /** Called with the duration in ms of each band convolution (diagnostics only). */\n onConvolution?: (milliseconds: number) => void;\n}\n\n/** Internal (not exported from the package): the base provider with the defocus disc applied in image space (#548). */\nexport function createDefocusImageSpaceProvider(input: DefocusImageSpaceProviderInput): PlanarSceneRadianceProvider {\n const { base, geometry, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const mmPerSite = input.sitePitchMicrometers / 1000;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - 1e-6 ? 0 : f < 1e-6 ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= 1e-6 && Math.abs(s.y - f.y) <= 1e-6)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - 1e-6)));\n const LW = W + 2 * M, LH = H + 2 * M;\n const win = input.window ?? { x: 0, y: 0, width: W, height: H };\n const lx0 = Math.max(0, win.x), lx1 = Math.min(LW, win.x + win.width + 2 * M);\n const ly0 = Math.max(0, win.y), ly1 = Math.min(LH, win.y + win.height + 2 * M);\n if (!(lx0 < lx1 && ly0 < ly1)) throw new InvalidConfigurationError(\"Defocus window must overlap the native raster.\");\n const NW = lx1 - lx0, gridWidth = NW + 2 * R;\n const kernels = wavelengthsNm.map((nm) => checkedSiteKernel(input.siteKernels(nm), R));\n const taps = kernels.map((kernel) => kernelTaps(kernel, R, gridWidth));\n const sharedKernel = kernels.every((kernel) => kernel === kernels[0]);\n const scale = input.metresPerFrameUnit, distance = input.distanceM;\n const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n // Lattice point (li, lj) of shift s, as a native sensor point in mm (+Y down): site centre plus the shift.\n const xMmOf = (li: number, s: { x: number }): number => (li - M + 0.5 + s.x - W / 2) * mmPerSite;\n const yMmOf = (lj: number, s: { y: number }): number => (lj - M + 0.5 + s.y - H / 2) * mmPerSite;\n // Bands per time (LRU over (time, band)): values[shift][node] holds G_t / F at the band's own lattice points.\n const cache = new Map<string, Float64Array[][]>();\n const capacity = CACHED_BANDS * Math.max(1, input.timesPerBand ?? 1);\n // The last band read, so consecutive queries of one band skip the cache key (most queries).\n let lastBand = -1, lastTime = NaN, lastValues: Float64Array[][] | undefined;\n function band(b: number, time: number): Float64Array[][] {\n if (b === lastBand && time === lastTime) return lastValues!;\n const values = bandOf(b, time);\n lastBand = b; lastTime = time; lastValues = values;\n return values;\n }\n function bandOf(b: number, time: number): Float64Array[][] {\n const key = time + \":\" + b, cached = cache.get(key);\n if (cached) { cache.delete(key); cache.set(key, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = ly0 + b * BAND_ROWS, rows = Math.min(BAND_ROWS, ly1 - y0), gridHeight = rows + 2 * R, size = gridWidth * gridHeight;\n const values = shifts.map((shift) => {\n // Each grid point's field factor and plane point (or material), shared by the spectral nodes.\n const factor = new Float64Array(size), u = new Float64Array(size), v = new Float64Array(size);\n const material = materialAt && materialRadiance ? new Int32Array(size) : undefined;\n for (let gy = 0; gy < gridHeight; gy++) {\n const yMm = yMmOf(y0 + gy - R, shift);\n for (let gx = 0; gx < gridWidth; gx++) {\n const k = gy * gridWidth + gx, look = geometry.lookOf(xMmOf(lx0 + gx - R, shift), yMm, time);\n if (!(look.z > 0)) throw new InvalidConfigurationError(\"lens.defocus: a lattice point's ray does not point toward the scene plane.\");\n // The base provider's own plane-point arithmetic for the outgoing direction −look.\n const t = distance / look.z;\n factor[k] = look.factor; u[k] = look.x * t / scale; v[k] = look.y * t / scale;\n if (material) material[k] = materialAt!(u[k]!, v[k]!);\n }\n }\n // The band's own lattice points' factors, to answer each query with G / F.\n const own = new Float64Array(rows * NW);\n for (let y = 0; y < rows; y++) for (let x = 0; x < NW; x++) own[y * NW + x] = factor[(y + R) * gridWidth + x + R]!;\n // One kernel for every node (the disc without diffraction) and fewer materials than nodes: the convolution is linear, so\n // G_λ = Σ_m L_m(λ)·(K ⊛ F·[material = m]); one convolution per material instead of one per node, the same sum regrouped.\n if (material && sharedKernel) {\n const present = [...new Set(material)];\n if (present.length < wavelengthsNm.length) {\n const perMaterial = present.map((m) => {\n const samples = new Float64Array(size);\n for (let k = 0; k < size; k++) if (material[k] === m) samples[k] = factor[k]!;\n return gatherInterior(samples, taps[0]!, gridWidth, NW, rows, R);\n });\n return wavelengthsNm.map((nm) => {\n const radiance = present.map((m) => materialRadiance!(m, nm)), out = new Float64Array(rows * NW);\n for (const value of radiance) if (!(value >= 0 && value <= 2 ** 100)) throw new InvalidConfigurationError(\"Irradiance samples must be finite, non-negative and within the declared magnitude.\");\n for (let k = 0; k < out.length; k++) {\n let sum = 0;\n for (let i = 0; i < present.length; i++) sum += radiance[i]! * perMaterial[i]![k]!;\n out[k] = sum / own[k]!;\n }\n return out;\n });\n }\n }\n return wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(size);\n if (material) {\n const radiance = new Map<number, number>();\n for (let k = 0; k < size; k++) {\n const m = material[k]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[k] = factor[k]! * value;\n }\n } else for (let k = 0; k < size; k++) samples[k] = factor[k]! * base.radianceAt(u[k]!, v[k]!, nm);\n const gathered = gatherInterior(samples, taps[w]!, gridWidth, NW, rows, R);\n for (let k = 0; k < gathered.length; k++) gathered[k] = gathered[k]! / own[k]!;\n return gathered;\n });\n });\n cache.set(key, values);\n if (cache.size > capacity) cache.delete(cache.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n /** The lattice key ((shift·LH + lj)·LW + li) of a look direction at time t, or undefined off the lattices or outside the window. */\n function keyOf(look: { x: number; y: number; z: number }, t: number): number | undefined {\n const point = geometry.sensorPointOf(look, t);\n if (point === undefined) return undefined;\n const fi = point.x / mmPerSite + W / 2 - 0.5, fj = point.y / mmPerSite + H / 2 - 0.5;\n for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) return undefined;\n return (s * LH + lj) * LW + li;\n }\n return undefined;\n }\n function valueOf(key: number, t: number, nm: number): number {\n const w = index.get(nm);\n if (w === undefined) throw new InvalidConfigurationError(\"Defocus query is off the sensor site lattice; the image-space convolution does not apply.\");\n const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;\n return band(Math.floor((lj - ly0) / BAND_ROWS), t)[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n function blurredAt(look: { x: number; y: number; z: number }, time: number, nm: number): number {\n const t = geometry.timeDependent ? time : 0, key = keyOf(look, t);\n if (key === undefined) throw new InvalidConfigurationError(\"Defocus query is off the sensor site lattice; the image-space convolution does not apply.\");\n return valueOf(key, t, nm);\n }\n const baseEvaluate = base.evaluateRadiance;\n const evaluateRadiance = (request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult => {\n const result = baseEvaluate.call(base, request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt({ x: -o.x, y: -o.y, z: -o.z }, request.timeSecondsFromExposureStart, request.wavelengthNanometers) };\n };\n // The result is the base result with only its radiance replaced, so an engine-built base evaluator keeps its mark. Its radiance is\n // a pure function of the lattice key (and, with rotation, the request time) and the wavelength, so the lean executor may read it by\n // key, as for the diffraction provider.\n if (isInternalSceneRadianceEvaluator(baseEvaluate)) {\n markInternalSceneRadianceEvaluator(evaluateRadiance);\n // With rotation the key also carries the request time, as an index into the distinct times seen (one per temporal midpoint).\n const times: number[] = [], timeIndex = new Map<number, number>(), latticeKeys = shifts.length * LH * LW;\n registerInternalRadianceAccess(evaluateRadiance, {\n tabulated: false,\n keyOfDirection(o, time): number | undefined {\n const t = geometry.timeDependent ? time : 0, key = keyOf({ x: -o.x, y: -o.y, z: -o.z }, t);\n if (key === undefined) return undefined;\n let index = timeIndex.get(t);\n if (index === undefined) { index = times.length; times.push(t); timeIndex.set(t, index); }\n return index * latticeKeys + key;\n },\n radianceOfKey(key, nm): number {\n const index = Math.floor(key / latticeKeys);\n return valueOf(key - index * latticeKeys, times[index]!, nm);\n }\n });\n }\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance,\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Defocus by image-space convolution does not take pupil rays.\");\n }\n };\n}\n\n/** Field-variation bounds of the image-space disc for one request (#548), recorded in the `lens.defocus` assumption. */\nexport interface DefocusFieldVariation {\n /** Sensor points the bounds were evaluated at: a grid of this many points per side over the native raster, edges included. */\n gridPointsPerSide: number;\n /**\n * Camera rotation (pitch or yaw tilts the scene plane in the camera frame): the largest change of the disc diameter, in\n * sites, between the axial depth of each scene point in the rotated camera frame and the subject distance, over the grid and\n * the rendered temporal midpoints. 0 for roll only; null without rotation.\n */\n rotationMaximumDiameterChangeSites: number | null;\n /**\n * Distortion: the largest deviation from 1 of the local scale of the distortion map (singular values of d distorted / d ideal)\n * over the grid: the relative disc-size difference to a model that blurs the ideal image and then distorts it. Null without distortion.\n */\n distortionMaximumLocalScaleDeviation: number | null;\n /**\n * A non-rectilinear projection: the largest change of the disc diameter, in sites, between the distance along each scene\n * point's ray and its axial depth (the thin-lens model uses the axial depth). Null for the rectilinear projection.\n */\n projectionMaximumDiameterChangeSites: number | null;\n}\n\n/** Internal: {@link DefocusFieldVariation} on a 9 × 9 grid of sensor points (the extremes of these smooth maps lie on the frame's edges). */\nexport function calculateDefocusFieldVariation(input: { geometry: PreparedDefocusImageSpaceGeometry; lensMapping?: PreparedEnvironmentLensFieldMapping;\n focalLengthMm: number; fNumber: number; focusDistanceM: number; subjectDistanceM: number; pitchMicrometers: number; nativeWidth: number; nativeHeight: number;\n angularVelocityRadPerSec: CameraAngularVelocityRadPerSec; temporalMidpointsSeconds: readonly number[]; diameterSites: number;\n discAt: (subjectDistanceM: number) => number }): DefocusFieldVariation {\n const { geometry, lensMapping, pitchMicrometers: pitch, nativeWidth: W, nativeHeight: H, subjectDistanceM: d, diameterSites, discAt } = input;\n const G = 9, points: { x: number; y: number }[] = [];\n for (let j = 0; j < G; j++) for (let i = 0; i < G; i++) points.push({ x: (i / (G - 1) - 0.5) * W * pitch / 1000, y: (j / (G - 1) - 0.5) * H * pitch / 1000 });\n let rotation: number | null = null;\n if (geometry.timeDependent) {\n rotation = 0;\n const omega = input.angularVelocityRadPerSec;\n for (const t of input.temporalMidpointsSeconds) {\n // The camera's optical axis at t in the reference axes; a scene point's axial depth in the rotated camera is P·axis.\n const axis = applyPhysicalCameraRotation({ x: 0, y: 0, z: 1 }, { pitch: omega.pitch * t, yaw: omega.yaw * t, roll: omega.roll * t }, \"camera-to-reference\");\n for (const p of points) {\n const look = geometry.lookOf(p.x, p.y, t), reach = d / look.z;\n const depth = reach * (look.x * axis.x + look.y * axis.y + look.z * axis.z);\n rotation = Math.max(rotation, Math.abs(discAt(depth) - diameterSites));\n }\n }\n }\n let distortion: number | null = null;\n if (lensMapping && lensMapping.mapping.distortion.kind !== \"none\") {\n distortion = 0;\n for (const p of points) {\n const scales = distortedImagePoint(lensMapping, undistortedImagePoint(lensMapping, { x: p.x, y: -p.y }).ideal);\n distortion = Math.max(distortion, scales.largestScale - 1, 1 - scales.smallestScale);\n }\n }\n let projection: number | null = null;\n if (lensMapping && lensMapping.mapping.projectionModel !== \"rectilinear\") {\n projection = 0;\n for (const p of points) {\n const look = geometry.lookOf(p.x, p.y, 0);\n projection = Math.max(projection, Math.abs(discAt(d / look.z) - diameterSites));\n }\n }\n return { gridPointsPerSide: G, rotationMaximumDiameterChangeSites: rotation, distortionMaximumLocalScaleDeviation: distortion, projectionMaximumDiameterChangeSites: projection };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"defocus-image-space-provider.js","sourceRoot":"","sources":["../../src/facade/defocus-image-space-provider.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * `simulateCapture`'s `lens.defocus` out of focus together with a lens field mapping (`lens.projection`,\n * `lens.distortion`), `lens.vignetting` or camera rotation (#548): the geometric defocus disc applied in image space,\n * on the site lattice of the sensor, instead of on the scene plane.\n *\n * Why the object-space path does not apply. `createDiffractedPlanarProvider` convolves the scene radiance on the plane\n * lattice that the sites see through one linear map (a still, rectilinear, distortion-free camera with the same\n * radiance-to-irradiance factor everywhere). A projection, a distortion or a rotation makes the map from sensor points\n * to plane points non-linear (or time-dependent), and vignetting makes the factor vary over the field, so the disc on\n * the plane is no longer the disc on the sensor.\n *\n * The image-space model. The environment PSF quadrature (`calculateSensorPsfIrradianceQuadrature`, the per-tap path\n * `lens.diffraction` falls back to) defines a sensor-plane PSF K as\n * E(q, λ, t) = Σ_k K(k)·F(s_k)·C·L(D_t(s_k), λ),\n * with s_k = q + k·p the tap source points on the sensor (p the site pitch), D_t the scene ray of a sensor point at\n * time t (inverse distortion, the declared projection, the camera rotation at t), F = T·A the field factor (vignetting\n * throughput T, applied once before the PSF spreads the light, and the distortion area factor A = 1/det J) and C the\n * paraxial radiance-to-irradiance factor π/(4·N_w²), the same everywhere. With K the defocus disc sampled on the site\n * lattice (`createDefocusDiscSiteKernel`), every source point of a site-centre query is another lattice point, so\n * E(q, λ, t) = C·G_t(q, λ), G_t = K ⊛ (F·L∘D_t) sampled on the lattice,\n * the same sum in a different floating-point order. This provider computes G_t once per spectral node and time on the\n * sensor lattice (in row bands, as the diffraction provider does) and answers the query of lattice point q at time t with\n * G_t(q, λ) / F(q); the environment multiplies by F(q)·C again, so each site gets C·G_t(q, λ). For the still,\n * rectilinear, distortion-free camera without vignetting it is the object-space convolution (F = 1 and D linear).\n *\n * The lattices. As in the diffraction provider, a pixel aperture or anti-aliasing spots add query offsets; each distinct\n * fractional offset gets its own shifted lattice of sensor points, and every tap of a query on one lattice is on the same\n * lattice. A query is located on its lattice by mapping its scene ray back to the sensor (camera rotation inverted at the\n * request's time, the forward projection, the forward distortion), within 1e-4 site; a query that lands on no lattice point\n * is refused rather than approximated.\n *\n * Time. With camera rotation each environment temporal midpoint is a still camera, so the disc is applied to that\n * instant's image in that instant's frame: one G_t per distinct request time, cached per band. Without rotation the image\n * does not depend on time and one G is kept. The facade refuses rotation with a rolling shutter (each row's instants differ).\n *\n * What is approximate is the disc itself (`lens.defocus` labels it; the facade records the field-variation bounds of\n * each combination), not this evaluation of it.\n */\n\n// #564: a defocus kernel above 64 sites (`largeKernel`) takes the run lattice of large-defocus-lattice.ts instead of the bands:\n// the samples F·L at the same lattice points, convolved by runs in fixed tiles, then divided by each queried point's own F.\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { hypot3 } from \"../core/portable-math.js\";\nimport { isInternalSceneRadianceEvaluator, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from \"../core/internal-radiance-evaluator.js\";\nimport type { SceneRadianceEvaluationRequest, SceneRadianceEvaluationResult } from \"../schema/scene-radiance.js\";\nimport { insideRadialImageCircle, lensProjectionDirectionValue, lensProjectionImagePointValue, type LensProjectionModel } from \"../camera/lens-projection.js\";\nimport { applyPhysicalCameraRotation, resolveProjectionDistanceMm, type CameraAngularVelocityRadPerSec } from \"../motion/camera-rotation.js\";\nimport { prepareIlluminationVignettingThroughput, type IlluminationVignettingProfile } from \"../optics/illumination-vignetting.js\";\nimport { distortedImagePoint, undistortedImagePoint, type PreparedEnvironmentLensFieldMapping } from \"../optics/sensor-environment-query.js\";\nimport { checkedSiteKernel, createZonedGather, gatherInterior, kernelTaps, type SiteKernelFieldZones } from \"./diffraction-provider.js\";\nimport type { PlanarSceneRadianceProvider } from \"./scene-radiance.js\";\nimport { LARGE_DEFOCUS_CACHE_BYTES, createLargeDefocusNodeLattice, type LargeDefocusKernel, type LargeDefocusNodeLattice } from \"./large-defocus-lattice.js\";\n\n/** Rows of native sites per band; bands kept per time. Banding changes memory only, never values. */\nconst BAND_ROWS = 32;\nconst CACHED_BANDS = 2;\nconst LATTICE_TOLERANCE_SITES = 1e-4;\n\n/** The camera geometry the environment uses for each site query (the same options as the site inputs). */\nexport interface DefocusImageSpaceGeometry {\n focalLengthMm: number;\n focusDistanceM: number;\n angularVelocityRadPerSec: CameraAngularVelocityRadPerSec;\n /** The site inputs' `lensFieldMapping`, prepared; omitted for the ideal rectilinear, distortion-free mapping. */\n lensMapping?: PreparedEnvironmentLensFieldMapping;\n /** The site inputs' radial-illumination-vignetting profile; omitted for unity field throughput. */\n vignetting?: IlluminationVignettingProfile;\n}\n\n/** Internal: the scene ray and field factor of sensor points, and the sensor point of a scene ray, for one geometry. */\nexport interface PreparedDefocusImageSpaceGeometry {\n /**\n * The unit look direction (toward the scene, reference camera axes at exposure start) of native sensor point (x, y) mm\n * (+X right, +Y down) at time t, and its field factor F = T·A (vignetting throughput × distortion area factor).\n */\n lookOf(xMm: number, yMm: number, timeSeconds: number): { x: number; y: number; z: number; factor: number };\n /** The native sensor point (mm, +Y down) whose scene ray at time t is the look direction; undefined outside the mapping. */\n sensorPointOf(look: { x: number; y: number; z: number }, timeSeconds: number): { x: number; y: number } | undefined;\n /** True with camera rotation: the ray of a sensor point depends on time. */\n timeDependent: boolean;\n}\n\n/** Internal: prepares {@link PreparedDefocusImageSpaceGeometry} with the environment's own conventions and arithmetic. */\nexport function prepareDefocusImageSpaceGeometry(geometry: DefocusImageSpaceGeometry): PreparedDefocusImageSpaceGeometry {\n const { focalLengthMm, focusDistanceM, angularVelocityRadPerSec: omega, lensMapping, vignetting } = geometry;\n // The projection scale: the thin-lens image distance at the finite focus, for every projection model (the environment's).\n const pd = resolveProjectionDistanceMm(focalLengthMm, focusDistanceM).projectionDistanceMm;\n const model: LensProjectionModel = lensMapping?.mapping.projectionModel ?? \"rectilinear\";\n // #569: with \"backward-ray\" (catalogue fisheyes), a point outside the image circle looks straight back, as the environment's mapped query does.\n const backward = lensMapping?.mapping.outsideImageCircle === \"backward-ray\";\n const timeDependent = omega.pitch !== 0 || omega.yaw !== 0 || omega.roll !== 0;\n // calculateIlluminationVignetting's throughput with the profile validated once (#563: the same numbers, without a result envelope per point).\n const throughputAt = vignetting ? prepareIlluminationVignettingThroughput(vignetting) : undefined;\n const displacement = (t: number): { pitch: number; yaw: number; roll: number } =>\n timeDependent ? { pitch: omega.pitch * t, yaw: omega.yaw * t, roll: omega.roll * t } : { pitch: 0, yaw: 0, roll: 0 };\n // The reference-to-camera rotation at the last time asked, as a matrix (its columns: the rotated basis vectors), so a lattice\n // lookup costs no trigonometry; the rotation is linear, so this equals rotating the vector, up to rounding.\n let matrixTime = NaN, m: number[] = [];\n const toCamera = (v: { x: number; y: number; z: number }, t: number): { x: number; y: number; z: number } => {\n if (t !== matrixTime) {\n const d = displacement(t), ex = applyPhysicalCameraRotation({ x: 1, y: 0, z: 0 }, d, \"reference-to-camera\"),\n ey = applyPhysicalCameraRotation({ x: 0, y: 1, z: 0 }, d, \"reference-to-camera\"), ez = applyPhysicalCameraRotation({ x: 0, y: 0, z: 1 }, d, \"reference-to-camera\");\n m = [ex.x, ey.x, ez.x, ex.y, ey.y, ez.y, ex.z, ey.z, ez.z];\n matrixTime = t;\n }\n return { x: m[0]! * v.x + m[1]! * v.y + m[2]! * v.z, y: m[3]! * v.x + m[4]! * v.y + m[5]! * v.z, z: m[6]! * v.x + m[7]! * v.y + m[8]! * v.z };\n };\n return {\n timeDependent,\n lookOf(xMm, yMm, t): { x: number; y: number; z: number; factor: number } {\n const image = { x: xMm, y: -yMm };\n const { ideal, distortionAreaFactor } = lensMapping ? undistortedImagePoint(lensMapping, image) : { ideal: image, distortionAreaFactor: 1 };\n let lx: number, ly: number, lz: number;\n if (model === \"rectilinear\") {\n // calculateInverseCameraRotationImageMapping: the captured ray (x/pd, y/pd, 1) in reference axes, projected at pd.\n const reference = applyPhysicalCameraRotation({ x: ideal.x / pd, y: ideal.y / pd, z: 1 }, displacement(t), \"camera-to-reference\");\n if (!(reference.z > 0)) throw new InvalidConfigurationError(\"lens.defocus: a lattice point's ray points to or behind the reference camera plane.\");\n lx = pd * (reference.x / reference.z); ly = pd * (reference.y / reference.z); lz = pd;\n } else {\n const reference = applyPhysicalCameraRotation(backward && !insideRadialImageCircle(model, pd, Math.hypot(ideal.x, ideal.y)) ? { x: 0, y: 0, z: -1 } :\n lensProjectionDirectionValue(model, pd, ideal.x, ideal.y), displacement(t), \"camera-to-reference\");\n lx = reference.x; ly = reference.y; lz = reference.z;\n }\n const length = hypot3(lx, ly, lz);\n const throughput = throughputAt ? throughputAt(image) : 1;\n return { x: lx / length, y: ly / length, z: lz / length, factor: throughput * distortionAreaFactor };\n },\n sensorPointOf(look, t): { x: number; y: number } | undefined {\n try {\n const c = timeDependent ? toCamera(look, t) : look;\n let ideal: { x: number; y: number };\n if (model === \"rectilinear\") {\n if (!(c.z > 0)) return undefined;\n ideal = { x: pd * (c.x / c.z), y: pd * (c.y / c.z) };\n } else ideal = lensProjectionImagePointValue(model, pd, c.x, c.y, c.z).imagePointMm;\n const image = lensMapping ? distortedImagePoint(lensMapping, ideal).pointMm : ideal;\n return Number.isFinite(image.x) && Number.isFinite(image.y) ? { x: image.x, y: -image.y } : undefined;\n } catch {\n return undefined;\n }\n }\n };\n}\n\nexport interface DefocusImageSpaceProviderInput {\n base: PlanarSceneRadianceProvider;\n geometry: PreparedDefocusImageSpaceGeometry;\n /** Each spectral node's kernel on the site lattice, (2·kernelRadius + 1)² taps, row-major (the disc, or diffraction ⊛ disc). */\n siteKernels: (wavelengthNm: number) => Float64Array;\n wavelengthsNm: readonly number[];\n kernelRadius: number;\n nativeWidth: number;\n nativeHeight: number;\n sitePitchMicrometers: number;\n /** Planar geometry of the base provider (plane distance and frame-unit scale), to find the plane point of a ray as it does. */\n distanceM: number;\n metresPerFrameUnit: number;\n /** Offsets of the query points from the site centres, in sites (+x right, +y down). Default: one zero offset. */\n queryOffsetsSites?: readonly { x: number; y: number }[];\n /** Region renders: the native sites that will be queried. Values are bit-identical to the whole render's. Default: the whole raster. */\n window?: { x: number; y: number; width: number; height: number };\n /** Most distinct request times kept per band (the temporal sample count). Default 1. */\n timesPerBand?: number;\n /** Called with the duration in ms of each band convolution (diagnostics only). */\n onConvolution?: (milliseconds: number) => void;\n /**\n * #564: a defocus kernel above the direct radius, convolved by runs in fixed tiles (`large-defocus-lattice.ts`), with each\n * node's diffraction kernel after it; used instead of `siteKernels` (`kernelRadius` is then unused).\n */\n largeKernel?: LargeDefocusKernel;\n /** #553: a field-varying kernel by zones (the cat's eye of lens.defocus), gathered instead of `siteKernels`, the same at every node. */\n fieldZones?: SiteKernelFieldZones;\n}\n\n/** Internal (not exported from the package): the base provider with the defocus disc applied in image space (#548). */\nexport function createDefocusImageSpaceProvider(input: DefocusImageSpaceProviderInput): PlanarSceneRadianceProvider {\n const { base, geometry, wavelengthsNm, nativeWidth: W, nativeHeight: H, kernelRadius: R } = input;\n const mmPerSite = input.sitePitchMicrometers / 1000;\n const index = new Map(wavelengthsNm.map((nm, i) => [nm, i]));\n const offsets = input.queryOffsetsSites ?? [{ x: 0, y: 0 }];\n const fraction = (value: number): number => { const f = value - Math.floor(value); return f > 1 - 1e-6 ? 0 : f < 1e-6 ? 0 : f; };\n const shifts: { x: number; y: number }[] = [];\n for (const o of offsets) {\n const f = { x: fraction(o.x), y: fraction(o.y) };\n if (!shifts.some((s) => Math.abs(s.x - f.x) <= 1e-6 && Math.abs(s.y - f.y) <= 1e-6)) shifts.push(f);\n }\n const M = Math.max(0, ...offsets.map((o) => Math.ceil(Math.max(Math.abs(o.x), Math.abs(o.y)) - 1e-6)));\n const LW = W + 2 * M, LH = H + 2 * M;\n const win = input.window ?? { x: 0, y: 0, width: W, height: H };\n const lx0 = Math.max(0, win.x), lx1 = Math.min(LW, win.x + win.width + 2 * M);\n const ly0 = Math.max(0, win.y), ly1 = Math.min(LH, win.y + win.height + 2 * M);\n if (!(lx0 < lx1 && ly0 < ly1)) throw new InvalidConfigurationError(\"Defocus window must overlap the native raster.\");\n const NW = lx1 - lx0, gridWidth = NW + 2 * R;\n const large = input.largeKernel;\n const kernels = large ? [] : wavelengthsNm.map((nm) => checkedSiteKernel(input.siteKernels(nm), R));\n const taps = kernels.map((kernel) => kernelTaps(kernel, R, gridWidth));\n const zonedGather = input.fieldZones ? createZonedGather(input.fieldZones, R, gridWidth, W, H, M) : undefined;\n const sharedKernel = !large && (zonedGather !== undefined || kernels.every((kernel) => kernel === kernels[0]));\n const scale = input.metresPerFrameUnit, distance = input.distanceM;\n const materialAt = base.chartMaterialAt?.bind(base), materialRadiance = base.materialRadiance?.bind(base);\n const now = (): number => globalThis.performance?.now() ?? Date.now();\n // Lattice point (li, lj) of shift s, as a native sensor point in mm (+Y down): site centre plus the shift.\n const xMmOf = (li: number, s: { x: number }): number => (li - M + 0.5 + s.x - W / 2) * mmPerSite;\n const yMmOf = (lj: number, s: { y: number }): number => (lj - M + 0.5 + s.y - H / 2) * mmPerSite;\n // Bands per time (LRU over (time, band)): values[shift][node] holds G_t / F at the band's own lattice points.\n const cache = new Map<string, Float64Array[][]>();\n const capacity = CACHED_BANDS * Math.max(1, input.timesPerBand ?? 1);\n // The last band read, so consecutive queries of one band skip the cache key (most queries).\n let lastBand = -1, lastTime = NaN, lastValues: Float64Array[][] | undefined;\n function band(b: number, time: number): Float64Array[][] {\n if (b === lastBand && time === lastTime) return lastValues!;\n const values = bandOf(b, time);\n lastBand = b; lastTime = time; lastValues = values;\n return values;\n }\n function bandOf(b: number, time: number): Float64Array[][] {\n const key = time + \":\" + b, cached = cache.get(key);\n if (cached) { cache.delete(key); cache.set(key, cached); return cached; }\n const started = input.onConvolution ? now() : 0;\n const y0 = ly0 + b * BAND_ROWS, rows = Math.min(BAND_ROWS, ly1 - y0), gridHeight = rows + 2 * R, size = gridWidth * gridHeight;\n const values = shifts.map((shift) => {\n // Each grid point's field factor and plane point (or material), shared by the spectral nodes.\n const factor = new Float64Array(size), u = new Float64Array(size), v = new Float64Array(size);\n const material = materialAt && materialRadiance ? new Int32Array(size) : undefined;\n for (let gy = 0; gy < gridHeight; gy++) {\n const yMm = yMmOf(y0 + gy - R, shift);\n for (let gx = 0; gx < gridWidth; gx++) {\n const k = gy * gridWidth + gx, look = geometry.lookOf(xMmOf(lx0 + gx - R, shift), yMm, time);\n if (!(look.z > 0)) throw new InvalidConfigurationError(\"lens.defocus: a lattice point's ray does not point toward the scene plane.\");\n // The base provider's own plane-point arithmetic for the outgoing direction −look.\n const t = distance / look.z;\n factor[k] = look.factor; u[k] = look.x * t / scale; v[k] = look.y * t / scale;\n if (material) material[k] = materialAt!(u[k]!, v[k]!);\n }\n }\n // The band's own lattice points' factors, to answer each query with G / F.\n const own = new Float64Array(rows * NW);\n for (let y = 0; y < rows; y++) for (let x = 0; x < NW; x++) own[y * NW + x] = factor[(y + R) * gridWidth + x + R]!;\n // One kernel for every node (the disc without diffraction) and fewer materials than nodes: the convolution is linear, so\n // G_λ = Σ_m L_m(λ)·(K ⊛ F·[material = m]); one convolution per material instead of one per node, the same sum regrouped.\n if (material && sharedKernel) {\n const present = [...new Set(material)];\n if (present.length < wavelengthsNm.length) {\n const perMaterial = present.map((m) => {\n const samples = new Float64Array(size);\n for (let k = 0; k < size; k++) if (material[k] === m) samples[k] = factor[k]!;\n return zonedGather ? zonedGather(samples, lx0, y0, NW, rows) : gatherInterior(samples, taps[0]!, gridWidth, NW, rows, R);\n });\n return wavelengthsNm.map((nm) => {\n const radiance = present.map((m) => materialRadiance!(m, nm)), out = new Float64Array(rows * NW);\n for (const value of radiance) if (!(value >= 0 && value <= 2 ** 100)) throw new InvalidConfigurationError(\"Irradiance samples must be finite, non-negative and within the declared magnitude.\");\n for (let k = 0; k < out.length; k++) {\n let sum = 0;\n for (let i = 0; i < present.length; i++) sum += radiance[i]! * perMaterial[i]![k]!;\n out[k] = sum / own[k]!;\n }\n return out;\n });\n }\n }\n return wavelengthsNm.map((nm, w) => {\n const samples = new Float64Array(size);\n if (material) {\n const radiance = new Map<number, number>();\n for (let k = 0; k < size; k++) {\n const m = material[k]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[k] = factor[k]! * value;\n }\n } else for (let k = 0; k < size; k++) samples[k] = factor[k]! * base.radianceAt(u[k]!, v[k]!, nm);\n const gathered = zonedGather ? zonedGather(samples, lx0, y0, NW, rows) : gatherInterior(samples, taps[w]!, gridWidth, NW, rows, R);\n for (let k = 0; k < gathered.length; k++) gathered[k] = gathered[k]! / own[k]!;\n return gathered;\n });\n });\n cache.set(key, values);\n if (cache.size > capacity) cache.delete(cache.keys().next().value!);\n if (input.onConvolution) input.onConvolution(now() - started);\n return values;\n }\n /** The lattice key ((shift·LH + lj)·LW + li) of a look direction at time t, or undefined off the lattices or outside the window. */\n function keyOf(look: { x: number; y: number; z: number }, t: number): number | undefined {\n const point = geometry.sensorPointOf(look, t);\n if (point === undefined) return undefined;\n const fi = point.x / mmPerSite + W / 2 - 0.5, fj = point.y / mmPerSite + H / 2 - 0.5;\n for (let s = 0; s < shifts.length; s++) {\n const shift = shifts[s]!, i = Math.round(fi - shift.x), j = Math.round(fj - shift.y);\n if (Math.abs(fi - shift.x - i) > LATTICE_TOLERANCE_SITES || Math.abs(fj - shift.y - j) > LATTICE_TOLERANCE_SITES) continue;\n const li = i + M, lj = j + M;\n if (li < lx0 || lj < ly0 || li >= lx1 || lj >= ly1) return undefined;\n return (s * LH + lj) * LW + li;\n }\n return undefined;\n }\n function valueOf(key: number, t: number, nm: number): number {\n const w = index.get(nm);\n if (w === undefined) throw new InvalidConfigurationError(\"Defocus query is off the sensor site lattice; the image-space convolution does not apply.\");\n const li = key % LW, rest = (key - li) / LW, lj = rest % LH, s = (rest - lj) / LH;\n if (large) return largeValue(s, t, w, li, lj);\n return band(Math.floor((lj - ly0) / BAND_ROWS), t)[s]![w]![((lj - ly0) % BAND_ROWS) * NW + li - lx0]!;\n }\n // #564: one run lattice per (time, shift) of the samples F·L at the lattice points, and the own field factors F by tile, so a\n // query is answered with (K ⊛ D ⊛ F·L) / F as on the band path.\n const largeLattices = new Map<string, { lattice: LargeDefocusNodeLattice; own: Map<number, Float64Array> }>();\n const largeLatticeCount = shifts.length * Math.max(1, input.timesPerBand ?? 1);\n // Lattice points at most `reach` beyond the lattice feed queried values: the defocus kernel's radius plus the diffraction kernel's.\n const reach = large ? large.runs.radius + (large.diffraction ? large.diffraction.radius : 0) : 0;\n function largeValue(s: number, time: number, w: number, li: number, lj: number): number {\n const key = time + \":\" + s;\n let entry = largeLattices.get(key);\n if (!entry) {\n const shift = shifts[s]!;\n const lattice = createLargeDefocusNodeLattice({ kernel: large!, wavelengthsNm, capacityBytes: LARGE_DEFOCUS_CACHE_BYTES / largeLatticeCount, ...(input.onConvolution ? { onTile: input.onConvolution } : {}),\n source: (x0, y0, width, height) => {\n const size = width * height, factor = new Float64Array(size), u = new Float64Array(size), v = new Float64Array(size);\n const material = materialAt && materialRadiance ? new Int32Array(size) : undefined, beyond = new Uint8Array(size);\n for (let y = 0; y < height; y++) {\n const yMm = yMmOf(y0 + y, shift);\n for (let x = 0; x < width; x++) {\n const k = y * width + x;\n // A fixed tile's source reaches past the lattice: points beyond its reach feed no queried value, so they are 0 and never\n // mapped (the lens profiles are checked only up to the reach).\n if (x0 + x < -reach || x0 + x >= LW + reach || y0 + y < -reach || y0 + y >= LH + reach) { beyond[k] = 1; continue; }\n const look = geometry.lookOf(xMmOf(x0 + x, shift), yMm, time);\n if (!(look.z > 0)) throw new InvalidConfigurationError(\"lens.defocus: a lattice point's ray does not point toward the scene plane.\");\n const t = distance / look.z;\n factor[k] = look.factor; u[k] = look.x * t / scale; v[k] = look.y * t / scale;\n if (material) material[k] = materialAt!(u[k]!, v[k]!);\n }\n }\n return (node: number): Float64Array => {\n const nm = wavelengthsNm[node]!, samples = new Float64Array(size);\n if (material) {\n const radiance = new Map<number, number>();\n for (let k = 0; k < size; k++) {\n if (beyond[k]) continue;\n const m = material[k]!;\n let value = radiance.get(m);\n if (value === undefined) { value = materialRadiance!(m, nm); radiance.set(m, value); }\n samples[k] = factor[k]! * value;\n }\n } else for (let k = 0; k < size; k++) if (!beyond[k]) samples[k] = factor[k]! * base.radianceAt(u[k]!, v[k]!, nm);\n return samples;\n };\n } });\n entry = { lattice, own: new Map() };\n largeLattices.set(key, entry);\n if (largeLattices.size > largeLatticeCount) largeLattices.delete(largeLattices.keys().next().value!);\n }\n // The own factor of the lattice point, by 64-point tiles (kept for the request: 8 bytes per lattice point read).\n const T = 64, tx = Math.floor(li / T), ty = Math.floor(lj / T), tileKey = ty * 1048576 + tx;\n let own = entry.own.get(tileKey);\n if (!own) {\n own = new Float64Array(T * T);\n const shift = shifts[s]!;\n // Only the lattice's own points are queried; the rest of the tile is never read (and may lie beyond the lens profiles).\n for (let y = 0; y < T && ty * T + y < LH; y++) { const yMm = yMmOf(ty * T + y, shift); for (let x = 0; x < T && tx * T + x < LW; x++) own[y * T + x] = geometry.lookOf(xMmOf(tx * T + x, shift), yMm, time).factor; }\n entry.own.set(tileKey, own);\n }\n return entry.lattice.valueAt(w, li, lj) / own[(lj - ty * T) * T + li - tx * T]!;\n }\n function blurredAt(look: { x: number; y: number; z: number }, time: number, nm: number): number {\n const t = geometry.timeDependent ? time : 0, key = keyOf(look, t);\n if (key === undefined) throw new InvalidConfigurationError(\"Defocus query is off the sensor site lattice; the image-space convolution does not apply.\");\n return valueOf(key, t, nm);\n }\n const baseEvaluate = base.evaluateRadiance;\n const evaluateRadiance = (request: Readonly<SceneRadianceEvaluationRequest>): SceneRadianceEvaluationResult => {\n const result = baseEvaluate.call(base, request), o = (request.target as { outgoingDirectionUnitVector: { x: number; y: number; z: number } }).outgoingDirectionUnitVector;\n return { ...result, spectralRadianceWattsPerSquareMeterSteradianNanometer: blurredAt({ x: -o.x, y: -o.y, z: -o.z }, request.timeSecondsFromExposureStart, request.wavelengthNanometers) };\n };\n // The result is the base result with only its radiance replaced, so an engine-built base evaluator keeps its mark. Its radiance is\n // a pure function of the lattice key (and, with rotation, the request time) and the wavelength, so the lean executor may read it by\n // key, as for the diffraction provider.\n if (isInternalSceneRadianceEvaluator(baseEvaluate)) {\n markInternalSceneRadianceEvaluator(evaluateRadiance);\n // With rotation the key also carries the request time, as an index into the distinct times seen (one per temporal midpoint).\n const times: number[] = [], timeIndex = new Map<number, number>(), latticeKeys = shifts.length * LH * LW;\n registerInternalRadianceAccess(evaluateRadiance, {\n tabulated: false,\n keyOfDirection(o, time): number | undefined {\n const t = geometry.timeDependent ? time : 0, key = keyOf({ x: -o.x, y: -o.y, z: -o.z }, t);\n if (key === undefined) return undefined;\n let index = timeIndex.get(t);\n if (index === undefined) { index = times.length; times.push(t); timeIndex.set(t, index); }\n return index * latticeKeys + key;\n },\n radianceOfKey(key, nm): number {\n const index = Math.floor(key / latticeKeys);\n return valueOf(key - index * latticeKeys, times[index]!, nm);\n }\n });\n }\n return {\n sceneId: base.sceneId, providerProfileId: base.providerProfileId, radianceAt: base.radianceAt,\n evaluateRadiance,\n evaluateApertureRadiance(): SceneRadianceEvaluationResult {\n throw new InvalidConfigurationError(\"Defocus by image-space convolution does not take pupil rays.\");\n }\n };\n}\n\n/** Field-variation bounds of the image-space disc for one request (#548), recorded in the `lens.defocus` assumption. */\nexport interface DefocusFieldVariation {\n /** Sensor points the bounds were evaluated at: a grid of this many points per side over the native raster, edges included. */\n gridPointsPerSide: number;\n /**\n * Camera rotation (pitch or yaw tilts the scene plane in the camera frame): the largest change of the disc diameter, in\n * sites, between the axial depth of each scene point in the rotated camera frame and the subject distance, over the grid and\n * the rendered temporal midpoints. 0 for roll only; null without rotation.\n */\n rotationMaximumDiameterChangeSites: number | null;\n /**\n * Distortion: the largest deviation from 1 of the local scale of the distortion map (singular values of d distorted / d ideal)\n * over the grid: the relative disc-size difference to a model that blurs the ideal image and then distorts it. Null without distortion.\n */\n distortionMaximumLocalScaleDeviation: number | null;\n /**\n * A non-rectilinear projection: the largest change of the disc diameter, in sites, between the distance along each scene\n * point's ray and its axial depth (the thin-lens model uses the axial depth). Null for the rectilinear projection.\n */\n projectionMaximumDiameterChangeSites: number | null;\n}\n\n/** Internal: {@link DefocusFieldVariation} on a 9 × 9 grid of sensor points (the extremes of these smooth maps lie on the frame's edges). */\nexport function calculateDefocusFieldVariation(input: { geometry: PreparedDefocusImageSpaceGeometry; lensMapping?: PreparedEnvironmentLensFieldMapping;\n focalLengthMm: number; fNumber: number; focusDistanceM: number; subjectDistanceM: number; pitchMicrometers: number; nativeWidth: number; nativeHeight: number;\n angularVelocityRadPerSec: CameraAngularVelocityRadPerSec; temporalMidpointsSeconds: readonly number[]; diameterSites: number;\n discAt: (subjectDistanceM: number) => number }): DefocusFieldVariation {\n const { geometry, lensMapping, pitchMicrometers: pitch, nativeWidth: W, nativeHeight: H, subjectDistanceM: d, diameterSites, discAt } = input;\n const G = 9, points: { x: number; y: number }[] = [];\n for (let j = 0; j < G; j++) for (let i = 0; i < G; i++) points.push({ x: (i / (G - 1) - 0.5) * W * pitch / 1000, y: (j / (G - 1) - 0.5) * H * pitch / 1000 });\n let rotation: number | null = null;\n if (geometry.timeDependent) {\n rotation = 0;\n const omega = input.angularVelocityRadPerSec;\n for (const t of input.temporalMidpointsSeconds) {\n // The camera's optical axis at t in the reference axes; a scene point's axial depth in the rotated camera is P·axis.\n const axis = applyPhysicalCameraRotation({ x: 0, y: 0, z: 1 }, { pitch: omega.pitch * t, yaw: omega.yaw * t, roll: omega.roll * t }, \"camera-to-reference\");\n for (const p of points) {\n const look = geometry.lookOf(p.x, p.y, t), reach = d / look.z;\n const depth = reach * (look.x * axis.x + look.y * axis.y + look.z * axis.z);\n rotation = Math.max(rotation, Math.abs(discAt(depth) - diameterSites));\n }\n }\n }\n let distortion: number | null = null;\n if (lensMapping && lensMapping.mapping.distortion.kind !== \"none\") {\n distortion = 0;\n for (const p of points) {\n const scales = distortedImagePoint(lensMapping, undistortedImagePoint(lensMapping, { x: p.x, y: -p.y }).ideal);\n distortion = Math.max(distortion, scales.largestScale - 1, 1 - scales.smallestScale);\n }\n }\n let projection: number | null = null;\n if (lensMapping && lensMapping.mapping.projectionModel !== \"rectilinear\") {\n projection = 0;\n for (const p of points) {\n const look = geometry.lookOf(p.x, p.y, 0);\n projection = Math.max(projection, Math.abs(discAt(d / look.z) - diameterSites));\n }\n }\n return { gridPointsPerSide: G, rotationMaximumDiameterChangeSites: rotation, distortionMaximumLocalScaleDeviation: distortion, projectionMaximumDiameterChangeSites: projection };\n}\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ResolveLensSampledPsfInput } from "../optics/lens-psf-profile.js";
|
|
2
2
|
import type { PlanarSceneRadianceProvider } from "./scene-radiance.js";
|
|
3
|
+
import { type LargeDefocusKernel } from "./large-defocus-lattice.js";
|
|
3
4
|
export interface DiffractedPlanarProviderInput {
|
|
4
5
|
base: PlanarSceneRadianceProvider;
|
|
5
6
|
/** The optical state of the sampled PSF, as for `resolveLensSampledPsf`, without field point and wavelength. Unused with `siteKernels`. */
|
|
@@ -41,6 +42,13 @@ export interface DiffractedPlanarProviderInput {
|
|
|
41
42
|
};
|
|
42
43
|
/** Called with the duration in ms of each band convolution (diagnostics only; never changes values). */
|
|
43
44
|
onConvolution?: (milliseconds: number) => void;
|
|
45
|
+
/**
|
|
46
|
+
* #564: a defocus kernel above the direct radius, convolved by runs in fixed tiles (`large-defocus-lattice.ts`), with each
|
|
47
|
+
* node's diffraction kernel after it; used instead of `siteKernels` and `psf` (`kernelRadius` is then unused).
|
|
48
|
+
*/
|
|
49
|
+
largeKernel?: LargeDefocusKernel;
|
|
50
|
+
/** #553: a field-varying kernel by zones (the cat's eye), used instead of `siteKernels` in the gather; needs `siteKernels`. */
|
|
51
|
+
fieldZones?: SiteKernelFieldZones;
|
|
44
52
|
}
|
|
45
53
|
/** Internal (not exported from the package): the base provider with diffraction applied as an object-space convolution. */
|
|
46
54
|
export declare function createDiffractedPlanarProvider(input: DiffractedPlanarProviderInput): PlanarSceneRadianceProvider;
|
|
@@ -60,3 +68,24 @@ export declare function gatherInterior(samples: Float64Array, taps: {
|
|
|
60
68
|
offsets: Int32Array;
|
|
61
69
|
weights: Float64Array;
|
|
62
70
|
}, gridWidth: number, width: number, rows: number, R: number): Float64Array;
|
|
71
|
+
/**
|
|
72
|
+
* #553: a field-varying site kernel (the cat's eye of `lens.defocus`) as square zones of the native raster, each zone with
|
|
73
|
+
* the kernel of its centre's field point, the same at every spectral node. A piecewise-constant (sectioned) approximation
|
|
74
|
+
* of a space-variant PSF (Denis, Thiébaut, Soulez, Becker and Mourya 2015, "Fast approximations of shift-variant blur",
|
|
75
|
+
* International Journal of Computer Vision 115:253–278, §3.1, open preprint arXiv:1502.03305).
|
|
76
|
+
*/
|
|
77
|
+
export interface SiteKernelFieldZones {
|
|
78
|
+
/** Zone side in native sites: zone (zx, zy) holds the native sites [zx·size, (zx + 1)·size) × [zy·size, (zy + 1)·size). */
|
|
79
|
+
size: number;
|
|
80
|
+
columns: number;
|
|
81
|
+
rows: number;
|
|
82
|
+
/** The kernel of zone zy·columns + zx, (2R + 1)² row-major taps with R the provider's `kernelRadius`. */
|
|
83
|
+
kernelOf(zone: number): Float64Array;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* #553: the band gather with {@link SiteKernelFieldZones}: out(x) = Σ_t K_z(t)·samples(x − t), z the zone of output site x
|
|
87
|
+
* (its native site, clamped to the raster for the margins of offset lattices). Each value is summed over its zone's taps in
|
|
88
|
+
* the order of {@link gatherInterior} (v outer, u inner, ascending), so a zoned gather whose zones all hold one kernel gives
|
|
89
|
+
* gatherInterior's bits. The zones' taps are built on first use and the last 3 rows of zones kept.
|
|
90
|
+
*/
|
|
91
|
+
export declare function createZonedGather(zones: SiteKernelFieldZones, R: number, gridWidth: number, nativeWidth: number, nativeHeight: number, margin: number): (samples: Float64Array, latticeX0: number, latticeY0: number, width: number, rows: number) => Float64Array;
|