@photivra/engine 2.7.0 → 2.8.1
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 +114 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/export-jpeg.js +25 -12
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +35 -5
- package/dist/capture/native-environment-lean.js +175 -16
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-raw.d.ts +9 -1
- package/dist/capture/native-environment-raw.js +14 -9
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-environment-tabulated.d.ts +58 -0
- package/dist/capture/native-environment-tabulated.js +91 -0
- package/dist/capture/native-environment-tabulated.js.map +1 -0
- package/dist/core/internal-radiance-evaluator.d.ts +28 -0
- package/dist/core/internal-radiance-evaluator.js +30 -0
- package/dist/core/internal-radiance-evaluator.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/facade/diffraction-provider.js +33 -12
- package/dist/facade/diffraction-provider.js.map +1 -1
- package/dist/facade/display-view.d.ts +14 -83
- package/dist/facade/display-view.js +331 -846
- package/dist/facade/display-view.js.map +1 -1
- package/dist/facade/expected-signal-setup.d.ts +65 -0
- package/dist/facade/expected-signal-setup.js +52 -0
- package/dist/facade/expected-signal-setup.js.map +1 -0
- package/dist/facade/expected-signal.d.ts +83 -0
- package/dist/facade/expected-signal.js +571 -0
- package/dist/facade/expected-signal.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +6 -0
- package/dist/facade/scene-radiance.js +31 -10
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.js +109 -28
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/simulate-display-view.js +26 -49
- package/dist/facade/simulate-display-view.js.map +1 -1
- package/dist/optics/site-diffraction-kernel.d.ts +5 -0
- package/dist/optics/site-diffraction-kernel.js +32 -0
- package/dist/optics/site-diffraction-kernel.js.map +1 -0
- package/dist/output/print-jpeg.js +70 -42
- package/dist/output/print-jpeg.js.map +1 -1
- package/docs/API_REFERENCE.md +1 -1
- package/docs/QUICK_START.md +1 -1
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +2 -2
- package/package.json +1 -1
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* without it every encoded file is byte-identical to 2.3.
|
|
29
29
|
* @see docs/QUICK_START.md
|
|
30
30
|
*/
|
|
31
|
-
import { markInternalSceneRadianceEvaluator } from "../core/internal-radiance-evaluator.js";
|
|
31
|
+
import { markInternalNativeTileReader, markInternalSceneRadianceEvaluator, registerInternalRadianceAccess } from "../core/internal-radiance-evaluator.js";
|
|
32
32
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
33
33
|
import { requireInputObject } from "../core/record-validation.js";
|
|
34
34
|
import { ENGINE_API_VERSION } from "../core/version.js";
|
|
@@ -47,6 +47,9 @@ import { createColorTemperatureWhiteBalanceIntent, resolveColorTemperatureWhiteB
|
|
|
47
47
|
import { createCaptureWhiteBalanceIntent } from "../capture/simulated-capture.js";
|
|
48
48
|
import { SENSOR_RAW_PRODUCER_NOISE_MODEL } from "../capture/sensor-raw-producer.js";
|
|
49
49
|
import { calculateNativeRawPlan, nativeRawMaximumProviderEvaluations, NATIVE_RAW_LIMITS } from "../capture/native-raw.js";
|
|
50
|
+
import { renderTabulatedNativeRaw, TABULATED_RELATIVE_TOLERANCE } from "../capture/native-environment-tabulated.js";
|
|
51
|
+
import { createDisplayViewExpectedSignal } from "./expected-signal.js";
|
|
52
|
+
import { buildExpectedSignalInput } from "./expected-signal-setup.js";
|
|
50
53
|
import { createNativeEnvironmentRawTask, createNativeEnvironmentRawRegionTask } from "../capture/native-environment-raw.js";
|
|
51
54
|
import { createNativeRawDevelopmentTask } from "../capture/native-raw-development.js";
|
|
52
55
|
import { parseSdrRenderingProfile } from "../output/sdr-rendering.js";
|
|
@@ -71,7 +74,7 @@ import { calculateSensorSpectralQuadrature } from "../sensor/spectral-quadrature
|
|
|
71
74
|
import { createDiffractionLimitedPsfProfile } from "../optics/diffraction-psf-profile.js";
|
|
72
75
|
import { createDiffractedPlanarProvider } from "./diffraction-provider.js";
|
|
73
76
|
import { resolveGenericPrimeLens } from "../equipment/generic-prime-lenses.js";
|
|
74
|
-
import {
|
|
77
|
+
import { executeEnvironmentSensorPhotoSignal, planEnvironmentSensorPhotoSignal } from "../sensor/environment-photo-signal.js";
|
|
75
78
|
import { calculateSiteEffectiveSaturationCode } from "../capture/raw-white-level.js";
|
|
76
79
|
import { prepareSensorColorDevelopment } from "../color/sensor-color-development.js";
|
|
77
80
|
import { resolveAntiAliasingSpatialKernel } from "../sensor/optical-stack.js";
|
|
@@ -80,7 +83,7 @@ import { prepareRgbGamutMapping } from "../color/gamut-mapping.js";
|
|
|
80
83
|
import { serializeNativeRawDng } from "../capture/native-raw-dng.js";
|
|
81
84
|
import { parseSensorReadoutConversionProfile, resolveSensorReadoutRegime } from "../sensor/raw-readout.js";
|
|
82
85
|
import { resolveChartScene, chartMaterialInputs, CHART_SCENE_PRESETS } from "./chart-scenes.js";
|
|
83
|
-
import { resolveCaptureIlluminant, calculateIlluminantIrradianceScale, buildPlanarSceneRadianceProvider, requireCallerScene, FACADE_SPECTRAL_RANGE_NANOMETERS, resolveChartSizeOption, PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W } from "./scene-radiance.js";
|
|
86
|
+
import { resolveCaptureIlluminant, calculateIlluminantIrradianceScale, buildPlanarSceneRadianceProvider, requireCallerScene, FACADE_SPECTRAL_RANGE_NANOMETERS, resolveChartSizeOption, PHOTOPIC_MAXIMUM_LUMINOUS_EFFICACY_LM_PER_W, planarProviderMaterialOfDirection } from "./scene-radiance.js";
|
|
84
87
|
/** Version of how the facade builds requests. It changes whenever the same input would build a different request. */
|
|
85
88
|
export const SIMULATE_CAPTURE_FACADE_VERSION = "1.0.0";
|
|
86
89
|
/** Default midpoint samples per axis of `sensor.pixelAperture: "box"`. */
|
|
@@ -139,6 +142,9 @@ const AHD_VALUE_REACH = 3;
|
|
|
139
142
|
/** Anti-aliasing filter limits: split points, and the largest offset in sites (bounds the scene work and the convolution margin). */
|
|
140
143
|
const AA_MAXIMUM_COMPONENTS = 16;
|
|
141
144
|
const AA_MAXIMUM_OFFSET_SITES = 4;
|
|
145
|
+
/** Channel responses kept across calls (`axisChannelResponse`): one entry per distinct sensor, exposure and optics state. */
|
|
146
|
+
const CHANNEL_RESPONSE_CACHE_SIZE = 8;
|
|
147
|
+
const channelResponseCache = new Map();
|
|
142
148
|
/** Default birefringent separation in sites: the two-spot MTF |cos(π·f·d)| then has its first zero at Nyquist, f = 1/(2·pitch). */
|
|
143
149
|
const AA_DEFAULT_SEPARATION_SITES = 1;
|
|
144
150
|
/** Parses `sensor.antiAliasing` into engine point-splitting components (offsets in µm, +x right, +y down). */
|
|
@@ -920,8 +926,15 @@ export async function runCapture(options, run, viewOption, renderView) {
|
|
|
920
926
|
// 2.6: a chart preset's evaluator is engine-built end to end (its results: the schema's exact keys, constant fields,
|
|
921
927
|
// the request's identifiers, deep-frozen FACADE_EVIDENCE, UNCERTAINTY and limitations, and an engine-computed
|
|
922
928
|
// radiance), so the native task may skip re-parsing the fixed parts. Caller scenes keep the full validation.
|
|
923
|
-
|
|
929
|
+
// #394: a caller material scene's evaluator is engine-built in the same way (its radiance comes from the validated materials;
|
|
930
|
+
// only materialAt, validated on every call, is the caller's).
|
|
931
|
+
const materialEvaluator = chart !== undefined || callerScene?.kind === "material-function";
|
|
932
|
+
if (materialEvaluator)
|
|
924
933
|
markInternalSceneRadianceEvaluator(provider.evaluateRadiance);
|
|
934
|
+
// #394: its results are materialRadiance(material at the queried point, wavelength), so the lean executor may tabulate them.
|
|
935
|
+
const materialOfDirection = planarProviderMaterialOfDirection(provider);
|
|
936
|
+
if (materialEvaluator && materialOfDirection && provider.materialRadiance)
|
|
937
|
+
registerInternalRadianceAccess(provider.evaluateRadiance, { keyOfDirection: materialOfDirection, radianceOfKey: provider.materialRadiance, tabulated: true });
|
|
925
938
|
assume("model.scene-radiometry", "model", "lambertian-plane", "Radiance = reflectance × irradiance / π on one plane; illuminance from K_m = 683 lm/W and the engine's analytic CIE 1931 ȳ fit.");
|
|
926
939
|
// Metering (CIPA DC-004 standard output sensitivity and camera equation) and exposure-mode resolution
|
|
927
940
|
const exposureOptions = allowKeys(top.exposure, "exposure", ["mode", "iso", "shutterSeconds", "compensationStops"]);
|
|
@@ -1303,13 +1316,16 @@ export async function runCapture(options, run, viewOption, renderView) {
|
|
|
1303
1316
|
const yieldControl = createHostYield().yieldControl;
|
|
1304
1317
|
const perSite = queriesPerSite * (diffraction && psf === diffractionPsf ? (2 * diffraction.kernelRadiusSamples + 1) ** 2 : 1);
|
|
1305
1318
|
let diffractionMs = 0, demosaicMs, encodeMs;
|
|
1306
|
-
const
|
|
1319
|
+
const diffractedProvider = (window) => diffraction && diffractionObjectSpace ? createDiffractedPlanarProvider({ base: provider, psf: diffractionPsf.configuration.psf,
|
|
1307
1320
|
wavelengthsNm: diffraction.profile.axes.wavelengthNm, kernelRadius: diffraction.kernelRadiusSamples, nativeWidth, nativeHeight, outputWidth: width,
|
|
1308
1321
|
sitePitchMicrometers: pitch, distanceM: subjectDistanceM, metresPerFrameUnit, onConvolution: (ms) => { diffractionMs += ms; },
|
|
1309
1322
|
// Region (2.6): convolve only the lattice the region's native sites query; the values are the whole render's.
|
|
1310
|
-
...(
|
|
1323
|
+
...(window ? { window } : {}),
|
|
1311
1324
|
// The environment queries each site at each aperture node minus each split offset (sites, +x right, +y down).
|
|
1312
1325
|
...(antiAliasing || boxSamples > 1 ? { queryOffsetsSites: apertureNodeOffsets(boxSamples).flatMap((node) => (antiAliasing ? antiAliasing.components : [{ offsetMicrometers: { x: 0, y: 0 } }]).map((c) => ({ x: node.x - c.offsetMicrometers.x / pitch, y: node.y - c.offsetMicrometers.y / pitch }))) } : {}) }) : provider;
|
|
1326
|
+
// Built on first use: a capture that takes the tabulated path (#394 step 2) never queries it, and its kernels cost a setup.
|
|
1327
|
+
let rawProviderBuilt;
|
|
1328
|
+
const rawProvider = () => (rawProviderBuilt ??= diffractedProvider(regionNative));
|
|
1313
1329
|
if (antiAliasing && perSite > 100_000)
|
|
1314
1330
|
fail("sensor.antiAliasing with these options needs " + perSite + " scene queries per site; the environment admits at most 100000.");
|
|
1315
1331
|
const evaluations = nativeWidth * nativeHeight * perSite;
|
|
@@ -1325,7 +1341,7 @@ export async function runCapture(options, run, viewOption, renderView) {
|
|
|
1325
1341
|
// is linear in the radiance node values and, for this planar scene, the same at every site (paraxial π/(4N_w²)).
|
|
1326
1342
|
const cx = Math.floor(nativeWidth / 2) & ~1, cy = Math.floor(nativeHeight / 2) & ~1;
|
|
1327
1343
|
const channelSites = { red: cy * nativeWidth + cx, green: cy * nativeWidth + Math.min(cx + 1, nativeWidth - 1), blue: Math.min(cy + 1, nativeHeight - 1) * nativeWidth + Math.min(cx + 1, nativeWidth - 1) };
|
|
1328
|
-
const
|
|
1344
|
+
const environments = {};
|
|
1329
1345
|
for (const channel of CHANNELS) {
|
|
1330
1346
|
if (channelAt(channelSites[channel] % nativeWidth, Math.floor(channelSites[channel] / nativeWidth)) !== channel)
|
|
1331
1347
|
fail(caller + " needs at least a 2 × 2 native raster.");
|
|
@@ -1336,13 +1352,36 @@ export async function runCapture(options, run, viewOption, renderView) {
|
|
|
1336
1352
|
environment.temporalSampleCount = 1;
|
|
1337
1353
|
delete environment.pupil;
|
|
1338
1354
|
delete environment.lensFieldMapping;
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1355
|
+
delete environment.evaluateRadiance;
|
|
1356
|
+
delete environment.evaluateApertureRadiance;
|
|
1357
|
+
environments[channel] = environment;
|
|
1358
|
+
}
|
|
1359
|
+
// The responses are a function of these records alone (the radiance is replaced per node), and a request split into region
|
|
1360
|
+
// tiles builds the same records for every tile, so they are kept across calls (the last CHANNEL_RESPONSE_CACHE_SIZE).
|
|
1361
|
+
const key = JSON.stringify(CHANNELS.map((c) => environments[c]));
|
|
1362
|
+
const copy = (responses) => Object.fromEntries(CHANNELS.map((c) => [c, new Map(responses[c])]));
|
|
1363
|
+
const cached = channelResponseCache.get(key);
|
|
1364
|
+
let electronsPerRadiance;
|
|
1365
|
+
if (cached) {
|
|
1366
|
+
channelResponseCache.delete(key);
|
|
1367
|
+
channelResponseCache.set(key, cached);
|
|
1368
|
+
electronsPerRadiance = copy(cached);
|
|
1369
|
+
}
|
|
1370
|
+
else {
|
|
1371
|
+
electronsPerRadiance = {};
|
|
1372
|
+
for (const channel of CHANNELS) {
|
|
1373
|
+
// Planned once per channel and executed per spectral node: calculateEnvironmentSensorPhotoSignal is this plan and execution.
|
|
1374
|
+
const photoPlan = planEnvironmentSensorPhotoSignal(environments[channel]);
|
|
1375
|
+
const electrons = (radiance) => executeEnvironmentSensorPhotoSignal(photoPlan, (request) => ({ ...provider.evaluateRadiance(request), spectralRadianceWattsPerSquareMeterSteradianNanometer: radiance(request.wavelengthNanometers) })).value
|
|
1376
|
+
.photo.value.photoSignal.expectedGeneratedElectronCount;
|
|
1377
|
+
const nodes = new Set();
|
|
1378
|
+
electrons((nm) => { nodes.add(nm); return 1; });
|
|
1379
|
+
electronsPerRadiance[channel] = new Map([...nodes].sort((a, b) => a - b).map((node) => [node, electrons((nm) => (nm === node ? 1 : 0))]));
|
|
1380
|
+
}
|
|
1381
|
+
// Callers get their own maps; the cached ones are never handed out.
|
|
1382
|
+
channelResponseCache.set(key, copy(electronsPerRadiance));
|
|
1383
|
+
if (channelResponseCache.size > CHANNEL_RESPONSE_CACHE_SIZE)
|
|
1384
|
+
channelResponseCache.delete(channelResponseCache.keys().next().value);
|
|
1346
1385
|
}
|
|
1347
1386
|
const wavelengths = [...new Set(CHANNELS.flatMap((c) => [...electronsPerRadiance[c].keys()]))].sort((a, b) => a - b);
|
|
1348
1387
|
// 2. Electrons → normalized RAW signal: (code − black)/(white − black) = e·d/(G·(W − B)) for the linear readout
|
|
@@ -1471,12 +1510,45 @@ export async function runCapture(options, run, viewOption, renderView) {
|
|
|
1471
1510
|
return () => { completed++; onProgress?.({ stage, completedTileCount: completed, totalTileCount: total }); };
|
|
1472
1511
|
};
|
|
1473
1512
|
const rawTick = progress("raw", regionNative ? regionNative.height * Math.ceil(regionNative.width / tileWidth) : plan.tileCount);
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1513
|
+
// #394: siteInput builds fresh site records per call and never changes them, so the native task plans them without a copy.
|
|
1514
|
+
const rawCallbacks = () => ({ readTile: markInternalNativeTileReader(async (request) => { const tile = await readTile(request); rawTick(); return tile; }),
|
|
1515
|
+
evaluateRadiance: rawProvider().evaluateRadiance, ...(pupil ? { evaluateApertureRadiance: provider.evaluateApertureRadiance } : {}), yieldControl });
|
|
1516
|
+
// #394 step 2: an engine-built planar scene (chart preset or caller material scene; still, rectilinear, no distortion, vignetting,
|
|
1517
|
+
// pupil rays or caller PSF) takes its expected electrons from the tabulated signal, verified per CFA phase against the chain.
|
|
1518
|
+
const tabulatedScene = chart !== undefined || callerScene?.kind === "material-function";
|
|
1519
|
+
let tabulated;
|
|
1520
|
+
if (tabulatedScene && !pupil && !lensFieldMapping && !vignetting && !lensPsf && !rotating && (!diffraction || diffractionObjectSpace) && provider.chartMaterialAt && provider.materialRadiance) {
|
|
1521
|
+
const { electronsPerRadiance, wavelengths } = axisChannelResponse("simulateCapture");
|
|
1522
|
+
const perNode = CHANNELS.map((c) => Float64Array.from(wavelengths, (nm) => electronsPerRadiance[c].get(nm) ?? 0));
|
|
1523
|
+
const sceneMaterials = chart ? chart.materials : callerScene.materials, materialRadiance = provider.materialRadiance;
|
|
1524
|
+
const { signalInput } = buildExpectedSignalInput({ nativeWidth, nativeHeight, width, wavelengths, perNode, apertureNodes: apertureNodeOffsets(boxSamples), boxSamples, antiAliasing, pitch,
|
|
1525
|
+
diffraction: diffraction ? { radius: diffraction.kernelRadiusSamples, psf: diffractionPsf.configuration.psf, profileWavelengths: diffraction.profile.axes.wavelengthNm } : undefined,
|
|
1526
|
+
materials: { materialAt: provider.chartMaterialAt, whiteRadiance: (nm) => irradianceScale * illuminant.shape.evaluate(nm) / Math.PI,
|
|
1527
|
+
list: [...sceneMaterials.map((m, index) => (m.kind === "neutral" ? { neutral: m.reflectance } : { radiance: (nm) => materialRadiance(index, nm) })),
|
|
1528
|
+
...(chartSize ? [{ neutral: chartSize.surroundReflectance }] : [])] },
|
|
1529
|
+
radianceAt: provider.radianceAt, imagingArea, focalLengthMm, focusDistanceM, subjectDistanceM, metresPerFrameUnit, caller: "simulateCapture" });
|
|
1530
|
+
// The verification reads only the region's top-left 2 × 2 block, so its diffraction convolves only that block's lattice; the
|
|
1531
|
+
// window never changes a value (see diffraction-provider.ts), so the chain it runs is the whole render's.
|
|
1532
|
+
const verificationProvider = diffractedProvider({ x: regionNative?.x ?? 0, y: regionNative?.y ?? 0, width: 2, height: 2 });
|
|
1533
|
+
tabulated = await renderTabulatedNativeRaw({ input: environmentRaw, region: regionNative, siteInput, evaluateRadiance: verificationProvider.evaluateRadiance,
|
|
1534
|
+
electrons: createDisplayViewExpectedSignal(signalInput), onTile: rawTick, tileWidth, yieldControl: () => yieldControl(), checkAbort });
|
|
1535
|
+
}
|
|
1536
|
+
let rawOutput;
|
|
1537
|
+
if (tabulated) {
|
|
1538
|
+
rawOutput = { raw: tabulated.raw, providerEvaluationCount: tabulated.providerEvaluationCount };
|
|
1539
|
+
// The verification's relative difference itself is not reported: it is a last-bits quantity, and captures use the JavaScript
|
|
1540
|
+
// engine's own Math functions, so it differs between engines while the results are the same.
|
|
1541
|
+
assume("raw.expectedSignal", "model", { method: "tabulated-expected-electrons", verificationSites: 4, tolerance: TABULATED_RELATIVE_TOLERANCE }, "Each native site's expected photo electrons are the tabulated sum over the pixel-aperture nodes, anti-aliasing spots, diffraction taps and spectral nodes (the display view's expected signal), " +
|
|
1542
|
+
"the same quantity the environment chain computes for this still, rectilinear, distortion-free planar scene, formed in another order, so it can differ in the last bits. The sensor stage (dark charge, Poisson draws, " +
|
|
1543
|
+
"read noise, ADC) is the native one with each site's own seeds. One site of each CFA phase ran the full chain: its readout was reproduced bit for bit and its electrons agreed within the tolerance. " +
|
|
1544
|
+
"diagnostics.providerEvaluationCount counts those sites' evaluator calls and the table's scene lookups.");
|
|
1545
|
+
}
|
|
1546
|
+
else {
|
|
1547
|
+
const rawTask = regionNative ? createNativeEnvironmentRawRegionTask(environmentRaw, regionNative, rawCallbacks()) :
|
|
1548
|
+
createNativeEnvironmentRawTask(environmentRaw, rawCallbacks());
|
|
1549
|
+
await runTask(rawTask);
|
|
1550
|
+
rawOutput = rawTask.takeOutput();
|
|
1551
|
+
}
|
|
1480
1552
|
// Region (2.3): the region's sites, re-described by a plan of the region raster (active area = the region), for development.
|
|
1481
1553
|
let developmentPlan = plan;
|
|
1482
1554
|
if (region && regionNative) {
|
|
@@ -1510,14 +1582,23 @@ export async function runCapture(options, run, viewOption, renderView) {
|
|
|
1510
1582
|
sampleSet: { imageStateId: "facade-pre-wb-raw", inputDomain: "relative-pre-wb-camera-linear-rgb", samples } });
|
|
1511
1583
|
finalRawInput = { raw: buildRawInput(intentOf(whiteBalanceState)), sceneBinding, maximumProviderEvaluations: environmentRaw.maximumProviderEvaluations };
|
|
1512
1584
|
const wbTick = progress("white-balance", plan.tileCount);
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1585
|
+
if (tabulated) {
|
|
1586
|
+
// #394: the RAW codes do not depend on the white-balance intent (it is development metadata), so the tabulated RAW is
|
|
1587
|
+
// kept with the plan of the measured intent instead of being rendered again.
|
|
1588
|
+
rawOutput = { ...rawOutput, raw: { ...rawOutput.raw, plan: calculateNativeRawPlan(finalRawInput.raw) } };
|
|
1589
|
+
for (let k = 0; k < plan.tileCount; k++)
|
|
1590
|
+
wbTick();
|
|
1591
|
+
}
|
|
1592
|
+
else {
|
|
1593
|
+
// A second lean RAW pass with the measured intent. It gives the same RAW as re-running the sensor stage on a
|
|
1594
|
+
// retained optical stage, and is faster: retaining the optical stage takes the first pass off the lean executor.
|
|
1595
|
+
const wbTask = createNativeEnvironmentRawTask(finalRawInput, {
|
|
1596
|
+
readTile: markInternalNativeTileReader(async (request) => { const tile = await readTile(request); wbTick(); return tile; }),
|
|
1597
|
+
evaluateRadiance: rawProvider().evaluateRadiance, ...(pupil ? { evaluateApertureRadiance: provider.evaluateApertureRadiance } : {}), yieldControl
|
|
1598
|
+
});
|
|
1599
|
+
await runTask(wbTask);
|
|
1600
|
+
rawOutput = wbTask.takeOutput();
|
|
1601
|
+
}
|
|
1521
1602
|
}
|
|
1522
1603
|
const wbMs = Date.now() - wbStarted, devStarted = Date.now();
|
|
1523
1604
|
const colorProfile = { schemaVersion: "0.1.0", profileId: IDS.spectral, profileVersion: SIMULATE_CAPTURE_FACADE_VERSION, colorSamplingProfileId: IDS.cfa,
|