rayzee 9.5.0 → 11.0.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/README.md +22 -20
- package/dist/{ArchiveImporter-xuUJiklP.js → ArchiveImporter-BRQvLggb.js} +12 -13
- package/dist/{BidirectionalIntegrator-C5PKjJoT.js → BidirectionalIntegrator-9lZQxFVH.js} +87 -87
- package/dist/BufferLayout-D_IBo2ci.js +150 -0
- package/dist/{ColorManagement-CheBCPaW.js → ColorManagement-oeEk7oSu.js} +171 -171
- package/dist/{NeuralRetouch-CW11yLZ_.js → NeuralRetouch-BCXylThH.js} +3 -3
- package/dist/{NeuralSuperRes-BekaecYg.js → NeuralSuperRes-sZAeS142.js} +3 -3
- package/dist/{PathTracer-Ccl9KOuF.js → PathTracer-CQPW06Mm.js} +2911 -2669
- package/dist/{PhysicalSky-Dv2PMFGW.js → PhysicalSky-BvqCw_dy.js} +2 -2
- package/dist/{RayzeeRenderer-BQxnzCTD.js → RayzeeRenderer-COpwotpU.js} +338 -329
- package/dist/{SolarLimb-ken-JbDK.js → SolarLimb-CPaeZVwz.js} +10 -10
- package/dist/{ToneMapGPU-BHi5JzIq.js → ToneMapGPU-CjU3osDd.js} +1 -1
- package/dist/{ViewTransforms-D0rTLBsX.js → ViewTransforms-CYN7bq2w.js} +2 -2
- package/dist/addons/archives.es.js +1 -1
- package/dist/addons/bidirectional.es.js +1 -1
- package/dist/addons/color.es.js +1 -1
- package/dist/addons/physical-sky.es.js +1 -1
- package/dist/rayzee-core.es.js +11 -11
- package/dist/rayzee.es.js +734 -599
- package/dist/rayzee.umd.js +102 -102
- package/dist/sceneCachePolicy-BSSsKY98.js +443 -0
- package/package.json +1 -1
- package/src/Color/ViewTransforms.js +5 -1
- package/src/EngineDefaults.js +59 -1032
- package/src/Headless.js +6 -5
- package/src/Passes/OIDNTemporalHistory.js +1 -1
- package/src/PathTracerApp.js +5 -3
- package/src/Processor/AssetLoader.js +6 -5
- package/src/Processor/BVHBuilder.js +10 -31
- package/src/Processor/BVHLeafFold.js +4 -6
- package/src/Processor/BVHRefitter.js +3 -46
- package/src/Processor/BufferLayout.js +291 -0
- package/src/Processor/EmissiveTriangleBuilder.js +1 -1
- package/src/Processor/GeometryExtractor.js +3 -3
- package/src/Processor/HostMemory.js +7 -1
- package/src/Processor/InstanceTable.js +1 -1
- package/src/Processor/MaterialPacking.js +2 -1
- package/src/Processor/PBRT/PBRTSceneBuilder.js +1 -1
- package/src/Processor/QueueManager.js +28 -3
- package/src/Processor/SceneProcessor.js +4 -2
- package/src/Processor/SplitBLAS.js +1 -1
- package/src/Processor/StorageTexturePool.js +22 -1
- package/src/Processor/TLASBuilder.js +1 -3
- package/src/Processor/TextureBuckets.js +237 -0
- package/src/Processor/TextureCreator.js +10 -1
- package/src/Processor/Workers/TexturesWorker.js +5 -6
- package/src/RayzeeRenderer.js +29 -32
- package/src/RenderSettings.js +26 -28
- package/src/Stages/ASVGF.js +8 -7
- package/src/Stages/AutoExposure.js +14 -5
- package/src/Stages/BilateralFilter.js +2 -1
- package/src/Stages/DenoiserSettings.js +182 -0
- package/src/Stages/EdgeFilter.js +2 -1
- package/src/Stages/MotionVector.js +1 -1
- package/src/Stages/NRD.js +2 -3
- package/src/Stages/NormalDepth.js +3 -2
- package/src/Stages/PathTracer.js +72 -4
- package/src/Stages/PathTracerStage.js +2 -1
- package/src/Stages/Variance.js +1 -1
- package/src/TSL/BVHTraversal.js +4 -1
- package/src/TSL/Common.js +1 -1
- package/src/TSL/EmissiveSampling.js +1 -1
- package/src/TSL/LightVisibility.js +111 -0
- package/src/TSL/LightsSampling.js +151 -15
- package/src/TSL/Random.js +1 -1
- package/src/TSL/ShadeKernel.js +88 -3
- package/src/TSL/TextureSampling.js +1 -1
- package/src/core.js +5 -9
- package/src/index.js +10 -21
- package/src/integrators/BidirectionalIntegrator.js +2 -1
- package/src/managers/CameraManager.js +17 -7
- package/src/managers/DenoisingManager.js +14 -10
- package/src/managers/EnvironmentManager.js +32 -13
- package/src/managers/MaterialDataManager.js +3 -3
- package/src/managers/UniformManager.js +2 -2
- package/dist/EngineDefaults-DH3bI5t-.js +0 -844
- package/dist/sceneCachePolicy-BmwYOYDu.js +0 -183
- /package/dist/{Logger-BnHghprG.js → Logger-dDDGj9Av.js} +0 -0
package/src/RenderSettings.js
CHANGED
|
@@ -9,6 +9,7 @@ import { toPortable, fromPortable } from './SceneState/portable.js';
|
|
|
9
9
|
*
|
|
10
10
|
* - `uniform` → forwarded to PathTracer.setUniform(uniform, value)
|
|
11
11
|
* - `handler` → calls a named handler method for multi-stage settings
|
|
12
|
+
* - neither → stored only; whoever needs it reads it
|
|
12
13
|
* - `reset` → whether to reset accumulation after the change (default true)
|
|
13
14
|
*
|
|
14
15
|
* Other layers add their own keys with {@link RenderSettings#define}.
|
|
@@ -77,14 +78,16 @@ const SETTING_ROUTES = {
|
|
|
77
78
|
renderTimeLimit: { handler: 'handleRenderTimeLimit', reset: false },
|
|
78
79
|
renderMode: { handler: 'handleRenderMode' },
|
|
79
80
|
integrator: { handler: 'handleIntegrator', reset: true },
|
|
81
|
+
shadowRays: { handler: 'handleShadowRays', reset: true },
|
|
80
82
|
environmentRotation: { handler: 'handleEnvironmentRotation' },
|
|
83
|
+
// Read when the kernels next build.
|
|
84
|
+
wavefrontSortMaterials: { handler: 'handleWavefrontSortMaterials', reset: false },
|
|
85
|
+
// No target: read when a model loads (setMaxTextureSize() also reprocesses the scene now).
|
|
86
|
+
maxTextureSize: { reset: false },
|
|
87
|
+
areaLightIntensityScale: { reset: false },
|
|
81
88
|
|
|
82
89
|
};
|
|
83
90
|
|
|
84
|
-
/**
|
|
85
|
-
* Default keys to extract from ENGINE_DEFAULTS for initializing the values map.
|
|
86
|
-
* Maps ENGINE_DEFAULTS key → RenderSettings key when they differ.
|
|
87
|
-
*/
|
|
88
91
|
/** Provenance tags for getEffective(). Add-only — hosts branch on them. */
|
|
89
92
|
export const SETTING_SOURCE = Object.freeze( {
|
|
90
93
|
DEFAULT: 'default',
|
|
@@ -93,11 +96,6 @@ export const SETTING_SOURCE = Object.freeze( {
|
|
|
93
96
|
MODE_PRESET: 'mode-preset',
|
|
94
97
|
} );
|
|
95
98
|
|
|
96
|
-
const DEFAULTS_KEY_MAP = {
|
|
97
|
-
bounces: 'maxBounces',
|
|
98
|
-
debugMode: 'visMode',
|
|
99
|
-
};
|
|
100
|
-
|
|
101
99
|
/**
|
|
102
100
|
* Single source of truth for all render parameters.
|
|
103
101
|
*
|
|
@@ -168,19 +166,21 @@ export class RenderSettings extends EventDispatcher {
|
|
|
168
166
|
|
|
169
167
|
/**
|
|
170
168
|
* Adds a setting of another layer — the viewer's, or an add-on's — with the same provenance, events, session
|
|
171
|
-
* saving and reset as the core's.
|
|
169
|
+
* saving and reset as the core's. The layer brings its own default.
|
|
172
170
|
* @param {string} key
|
|
173
171
|
* @param {Object} route
|
|
172
|
+
* @param {*} [route.default] - the value until someone sets one; else the one this store was built with
|
|
174
173
|
* @param {function(*, *): void} route.apply - called with ( value, prev ) on every change, and by applyAll()
|
|
175
174
|
* @param {boolean} [route.reset=true] - reset accumulation after a change
|
|
176
175
|
*/
|
|
177
|
-
define( key, { apply, reset = true } ) {
|
|
176
|
+
define( key, { default: initial, apply, reset = true } ) {
|
|
178
177
|
|
|
179
178
|
if ( this._routes.has( key ) ) throw new Error( `setting "${key}" is already defined` );
|
|
180
179
|
this._routes.set( key, { apply, reset } );
|
|
181
|
-
|
|
180
|
+
const value = initial !== undefined ? initial : this._defaults[ key ];
|
|
181
|
+
if ( ! this._values.has( key ) && value !== undefined ) {
|
|
182
182
|
|
|
183
|
-
this._values.set( key,
|
|
183
|
+
this._values.set( key, value );
|
|
184
184
|
this._sources.set( key, SETTING_SOURCE.DEFAULT );
|
|
185
185
|
|
|
186
186
|
}
|
|
@@ -289,12 +289,24 @@ export class RenderSettings extends EventDispatcher {
|
|
|
289
289
|
|
|
290
290
|
},
|
|
291
291
|
|
|
292
|
+
handleShadowRays: ( value ) => {
|
|
293
|
+
|
|
294
|
+
stages.pathTracer?.setShadowRays?.( value );
|
|
295
|
+
|
|
296
|
+
},
|
|
297
|
+
|
|
292
298
|
handleEnvironmentRotation: ( value ) => {
|
|
293
299
|
|
|
294
300
|
stages.pathTracer?.environment.setEnvironmentRotation( value );
|
|
295
301
|
|
|
296
302
|
},
|
|
297
303
|
|
|
304
|
+
handleWavefrontSortMaterials: ( value ) => {
|
|
305
|
+
|
|
306
|
+
if ( stages.pathTracer ) stages.pathTracer.sortMaterials = value;
|
|
307
|
+
|
|
308
|
+
},
|
|
309
|
+
|
|
298
310
|
handleInteractionModeEnabled: ( value ) => {
|
|
299
311
|
|
|
300
312
|
stages.pathTracer?.setInteractionModeEnabled( value );
|
|
@@ -503,7 +515,7 @@ export class RenderSettings extends EventDispatcher {
|
|
|
503
515
|
|
|
504
516
|
} else {
|
|
505
517
|
|
|
506
|
-
route.apply( value, prev );
|
|
518
|
+
route.apply?.( value, prev );
|
|
507
519
|
|
|
508
520
|
}
|
|
509
521
|
|
|
@@ -511,11 +523,9 @@ export class RenderSettings extends EventDispatcher {
|
|
|
511
523
|
|
|
512
524
|
/**
|
|
513
525
|
* Populates the values map from ENGINE_DEFAULTS.
|
|
514
|
-
* Handles key renames via DEFAULTS_KEY_MAP.
|
|
515
526
|
*/
|
|
516
527
|
_initDefaults( defaults ) {
|
|
517
528
|
|
|
518
|
-
// Keys that exist in both SETTING_ROUTES and ENGINE_DEFAULTS (direct match)
|
|
519
529
|
for ( const key of Object.keys( SETTING_ROUTES ) ) {
|
|
520
530
|
|
|
521
531
|
if ( key in defaults ) {
|
|
@@ -527,18 +537,6 @@ export class RenderSettings extends EventDispatcher {
|
|
|
527
537
|
|
|
528
538
|
}
|
|
529
539
|
|
|
530
|
-
// Keys where ENGINE_DEFAULTS uses a different name
|
|
531
|
-
for ( const [ defaultsKey, settingsKey ] of Object.entries( DEFAULTS_KEY_MAP ) ) {
|
|
532
|
-
|
|
533
|
-
if ( defaultsKey in defaults ) {
|
|
534
|
-
|
|
535
|
-
this._values.set( settingsKey, defaults[ defaultsKey ] );
|
|
536
|
-
this._sources.set( settingsKey, SETTING_SOURCE.DEFAULT );
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
}
|
|
541
|
-
|
|
542
540
|
}
|
|
543
541
|
|
|
544
542
|
}
|
package/src/Stages/ASVGF.js
CHANGED
|
@@ -5,7 +5,8 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
|
|
|
5
5
|
import { HalfFloatType, FloatType, RGBAFormat, NearestFilter, LinearFilter, Box2, Vector2 } from 'three';
|
|
6
6
|
import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
7
7
|
import { luminance } from '../TSL/Common.js';
|
|
8
|
-
import {
|
|
8
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
9
|
+
import { ALBEDO_EPS, ASVGF_QUALITY_PRESETS } from './DenoiserSettings.js';
|
|
9
10
|
|
|
10
11
|
// Replace NaN/±Inf with a bounded value so one firefly can't permanently poison the
|
|
11
12
|
// temporal EMA (mix() propagates NaN forever). Per-channel: NaN (x!=x) → 0, ±Inf → [0,1e7].
|
|
@@ -39,14 +40,14 @@ export class ASVGF extends RenderStage {
|
|
|
39
40
|
|
|
40
41
|
this.renderer = renderer;
|
|
41
42
|
|
|
42
|
-
this.temporalAlpha = uniform( options.temporalAlpha ??
|
|
43
|
-
// > 0 is required for firefly rejection, not just anti-lag — see
|
|
44
|
-
this.gradientStrength = uniform( options.gradientStrength ??
|
|
43
|
+
this.temporalAlpha = uniform( options.temporalAlpha ?? ASVGF_QUALITY_PRESETS.medium.temporalAlpha );
|
|
44
|
+
// > 0 is required for firefly rejection, not just anti-lag — see DENOISER_DEFAULTS.
|
|
45
|
+
this.gradientStrength = uniform( options.gradientStrength ?? ASVGF_QUALITY_PRESETS.medium.gradientStrength );
|
|
45
46
|
// σ multiplier for the per-pixel noise floor (NRD luminanceSigmaScale ≈ 2).
|
|
46
|
-
this.gradientSigmaScale = uniform( options.gradientSigmaScale ??
|
|
47
|
+
this.gradientSigmaScale = uniform( options.gradientSigmaScale ?? ASVGF_QUALITY_PRESETS.medium.gradientSigmaScale );
|
|
47
48
|
// Secondary relative floor on the normalised gradient (0 = rely on σ alone).
|
|
48
|
-
this.gradientNoiseFloor = uniform( options.gradientNoiseFloor ??
|
|
49
|
-
this.maxAccumFrames = uniform( options.maxAccumFrames ??
|
|
49
|
+
this.gradientNoiseFloor = uniform( options.gradientNoiseFloor ?? ASVGF_QUALITY_PRESETS.medium.gradientNoiseFloor );
|
|
50
|
+
this.maxAccumFrames = uniform( options.maxAccumFrames ?? ASVGF_QUALITY_PRESETS.medium.maxAccumFrames );
|
|
50
51
|
|
|
51
52
|
this.resW = uniform( options.width || 1 );
|
|
52
53
|
this.resH = uniform( options.height || 1 );
|
|
@@ -7,6 +7,15 @@ import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
|
7
7
|
import { luminance } from '../TSL/Common.js';
|
|
8
8
|
|
|
9
9
|
// ── Histogram constants ────────────────────────────────────
|
|
10
|
+
export const AUTO_EXPOSURE_DEFAULTS = {
|
|
11
|
+
autoExposure: false,
|
|
12
|
+
autoExposureKeyValue: 0.18,
|
|
13
|
+
autoExposureMinExposure: 0.1,
|
|
14
|
+
autoExposureMaxExposure: 20.0,
|
|
15
|
+
autoExposureAdaptSpeedBright: 3.0,
|
|
16
|
+
autoExposureAdaptSpeedDark: 0.5,
|
|
17
|
+
};
|
|
18
|
+
|
|
10
19
|
const NUM_BINS = 256;
|
|
11
20
|
const MIN_LOG_LUM = - 8.0; // ln(~0.00034) — very dark
|
|
12
21
|
const MAX_LOG_LUM = 6.0; // ln(~403) — bright specular
|
|
@@ -103,11 +112,11 @@ export class AutoExposure extends RenderStage {
|
|
|
103
112
|
|
|
104
113
|
// ── Adaptation uniforms ──────────────────────────
|
|
105
114
|
|
|
106
|
-
this.keyValueU = uniform( options.keyValue ??
|
|
107
|
-
this.minExposureU = uniform( options.minExposure ??
|
|
108
|
-
this.maxExposureU = uniform( options.maxExposure ??
|
|
109
|
-
this.adaptSpeedBrightU = uniform( options.adaptSpeedBright ??
|
|
110
|
-
this.adaptSpeedDarkU = uniform( options.adaptSpeedDark ??
|
|
115
|
+
this.keyValueU = uniform( options.keyValue ?? AUTO_EXPOSURE_DEFAULTS.autoExposureKeyValue );
|
|
116
|
+
this.minExposureU = uniform( options.minExposure ?? AUTO_EXPOSURE_DEFAULTS.autoExposureMinExposure );
|
|
117
|
+
this.maxExposureU = uniform( options.maxExposure ?? AUTO_EXPOSURE_DEFAULTS.autoExposureMaxExposure );
|
|
118
|
+
this.adaptSpeedBrightU = uniform( options.adaptSpeedBright ?? AUTO_EXPOSURE_DEFAULTS.autoExposureAdaptSpeedBright );
|
|
119
|
+
this.adaptSpeedDarkU = uniform( options.adaptSpeedDark ?? AUTO_EXPOSURE_DEFAULTS.autoExposureAdaptSpeedDark );
|
|
111
120
|
this.epsilonU = uniform( options.epsilon ?? 0.0001 );
|
|
112
121
|
this.deltaTimeU = uniform( 1.0 / 60.0 );
|
|
113
122
|
this.isFirstFrameU = uniform( 1.0 ); // 1.0 = true
|
|
@@ -4,7 +4,8 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
|
|
|
4
4
|
import { HalfFloatType, RGBAFormat, LinearFilter, Box2, Vector2 } from 'three';
|
|
5
5
|
import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
6
6
|
import { luminance } from '../TSL/Common.js';
|
|
7
|
-
import {
|
|
7
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
8
|
+
import { ALBEDO_EPS } from './DenoiserSettings.js';
|
|
8
9
|
|
|
9
10
|
// SVGF bilateral edge-stopping weight. All three φ params are relative
|
|
10
11
|
// tolerances (unitless fractions) so the filter is scale-invariant across
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
|
|
2
|
+
// Ray distance NormalDepth writes on a miss. Max finite half-float, so miss−miss diffs stay 0
|
|
3
|
+
// rather than Inf−Inf=NaN.
|
|
4
|
+
export const GBUFFER_MISS_DEPTH = 65504.0;
|
|
5
|
+
export const GBUFFER_MISS_THRESHOLD = 6e4;
|
|
6
|
+
|
|
7
|
+
// Albedo demodulation safety floor. ASVGF and BilateralFilter MUST use the
|
|
8
|
+
// same value — demod (`color / safeAlbedo`) and remod (`lighting * safeAlbedo`)
|
|
9
|
+
// only round-trip exactly when both sides agree.
|
|
10
|
+
export const ALBEDO_EPS = 0.01;
|
|
11
|
+
|
|
12
|
+
export const ASVGF_QUALITY_PRESETS = {
|
|
13
|
+
// phiColor / phiDepth are RELATIVE tolerances (fractions). Bigger = more
|
|
14
|
+
// permissive. The adaptive temporal gradient (gradientStrength > 0) is always
|
|
15
|
+
// on: it measures real change in units of noise σ (gradientSigmaScale), so a
|
|
16
|
+
// static scene reads ~0 (no convergence penalty) and only moving lights / anim
|
|
17
|
+
// / disocclusion drop history. See ASVGF._buildGradientCompute.
|
|
18
|
+
low: {
|
|
19
|
+
temporalAlpha: 0.1,
|
|
20
|
+
gradientStrength: 0.8,
|
|
21
|
+
gradientSigmaScale: 2.5,
|
|
22
|
+
gradientNoiseFloor: 0.05,
|
|
23
|
+
atrousIterations: 3,
|
|
24
|
+
phiColor: 1.0,
|
|
25
|
+
phiNormal: 64.0,
|
|
26
|
+
phiDepth: 0.1,
|
|
27
|
+
phiLuminance: 6.0,
|
|
28
|
+
maxAccumFrames: 16,
|
|
29
|
+
varianceBoost: 0.5
|
|
30
|
+
},
|
|
31
|
+
medium: {
|
|
32
|
+
temporalAlpha: 0.03,
|
|
33
|
+
gradientStrength: 1.0,
|
|
34
|
+
gradientSigmaScale: 2.5,
|
|
35
|
+
gradientNoiseFloor: 0.05,
|
|
36
|
+
atrousIterations: 4,
|
|
37
|
+
phiColor: 0.5,
|
|
38
|
+
phiNormal: 128.0,
|
|
39
|
+
phiDepth: 0.05,
|
|
40
|
+
phiLuminance: 4.0,
|
|
41
|
+
maxAccumFrames: 64,
|
|
42
|
+
varianceBoost: 1.0
|
|
43
|
+
},
|
|
44
|
+
high: {
|
|
45
|
+
temporalAlpha: 0.0,
|
|
46
|
+
gradientStrength: 1.0,
|
|
47
|
+
gradientSigmaScale: 2.5,
|
|
48
|
+
gradientNoiseFloor: 0.05,
|
|
49
|
+
atrousIterations: 6,
|
|
50
|
+
phiColor: 0.3,
|
|
51
|
+
phiNormal: 256.0,
|
|
52
|
+
phiDepth: 0.02,
|
|
53
|
+
phiLuminance: 2.0,
|
|
54
|
+
maxAccumFrames: 128,
|
|
55
|
+
varianceBoost: 1.5
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// normHitDist = hitDist / (A + B·viewZ). A constant, not a uniform: the Shade write and the NRD
|
|
60
|
+
// decode must agree, and the normalization is a pure round trip.
|
|
61
|
+
export const NRD_HIT_DIST_A = 3.0;
|
|
62
|
+
export const NRD_HIT_DIST_B = 0.1;
|
|
63
|
+
|
|
64
|
+
// NRD ReBLUR port (Stages/NRD.js). Names follow nrd::ReblurSettings so NVIDIA's tuning notes apply.
|
|
65
|
+
export const NRD_DEFAULTS = {
|
|
66
|
+
maxAccumulatedFrameNum: 30,
|
|
67
|
+
maxFastAccumulatedFrameNum: 6,
|
|
68
|
+
maxStabilizedFrameNum: 63,
|
|
69
|
+
historyFixFrameNum: 3,
|
|
70
|
+
historyFixBasePixelStride: 14,
|
|
71
|
+
prepassBlurRadius: 30,
|
|
72
|
+
minBlurRadius: 1,
|
|
73
|
+
maxBlurRadius: 30,
|
|
74
|
+
lobeAngleFraction: 0.15,
|
|
75
|
+
roughnessFraction: 0.15,
|
|
76
|
+
planeDistanceSensitivity: 0.02,
|
|
77
|
+
minHitDistanceWeight: 0.1,
|
|
78
|
+
fastHistoryClampingSigmaScale: 2.0,
|
|
79
|
+
fireflySuppressorMinRelativeScale: 2.0,
|
|
80
|
+
enableAntiFirefly: true,
|
|
81
|
+
antilagLuminanceSigmaScale: 2.0,
|
|
82
|
+
antilagLuminanceSensitivity: 3.0,
|
|
83
|
+
disocclusionThreshold: 0.01,
|
|
84
|
+
convergenceS: 1.0,
|
|
85
|
+
convergenceB: 0.2,
|
|
86
|
+
convergenceP: 0.8,
|
|
87
|
+
// Share of the lobe the normal weight accepts before any history exists. NRD's own constant is
|
|
88
|
+
// 0.75, which its source flags as probably too much; at that width it smears curved surfaces.
|
|
89
|
+
lobeVolumePercent: 0.1,
|
|
90
|
+
// Progressive handover: input sample count at which the denoiser passes the render through untouched.
|
|
91
|
+
// 0 = 2 · maxAccumulatedFrameNum.
|
|
92
|
+
handoverFrames: 0,
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Keys a preset may override. Applying one resets every key to its default first, so a preset only
|
|
96
|
+
// states its deltas and `medium` can be empty.
|
|
97
|
+
export const NRD_PRESET_KEYS = [
|
|
98
|
+
'maxAccumulatedFrameNum', 'maxFastAccumulatedFrameNum', 'maxStabilizedFrameNum',
|
|
99
|
+
'historyFixFrameNum', 'prepassBlurRadius', 'maxBlurRadius', 'enableAntiFirefly',
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
export const NRD_QUALITY_PRESETS = {
|
|
103
|
+
// Short history + no pre-pass: most responsive, noisiest.
|
|
104
|
+
low: {
|
|
105
|
+
maxAccumulatedFrameNum: 16,
|
|
106
|
+
maxFastAccumulatedFrameNum: 4,
|
|
107
|
+
maxStabilizedFrameNum: 16,
|
|
108
|
+
historyFixFrameNum: 2,
|
|
109
|
+
prepassBlurRadius: 0,
|
|
110
|
+
maxBlurRadius: 20,
|
|
111
|
+
enableAntiFirefly: false,
|
|
112
|
+
},
|
|
113
|
+
// nrd::ReblurSettings defaults.
|
|
114
|
+
medium: {},
|
|
115
|
+
// Longer history and wider kernels: smoother, more lag on lighting change.
|
|
116
|
+
high: {
|
|
117
|
+
maxAccumulatedFrameNum: 45,
|
|
118
|
+
maxFastAccumulatedFrameNum: 8,
|
|
119
|
+
historyFixFrameNum: 4,
|
|
120
|
+
prepassBlurRadius: 40,
|
|
121
|
+
maxBlurRadius: 40,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const ASVGF_MEDIUM = ASVGF_QUALITY_PRESETS.medium;
|
|
126
|
+
|
|
127
|
+
// What the live denoisers, the final OIDN pass and the AI upscaler start with; a host's own state seeds from these.
|
|
128
|
+
export const DENOISER_DEFAULTS = {
|
|
129
|
+
denoiserStrategy: 'none', // the live view's denoiser: 'none' | 'edgeaware' | 'asvgf' | 'nrd' | 'oidn'
|
|
130
|
+
|
|
131
|
+
// EdgeAware denoiser (spatial-only SVGF à-trous). filterStrength: final blend
|
|
132
|
+
// (0 = raw, 1 = filtered). edgeAtrousIterations: à-trous passes (step 1,2,4,8,16).
|
|
133
|
+
// edgePhiLuminance: variance-scaled luminance edge-stop. edgePhiNormal: normal cone
|
|
134
|
+
// exponent. edgePhiDepth: RELATIVE depth tolerance (fraction of ray distance).
|
|
135
|
+
filterStrength: 1.0,
|
|
136
|
+
edgeAtrousIterations: 5,
|
|
137
|
+
edgePhiLuminance: 4.0,
|
|
138
|
+
edgePhiNormal: 64.0,
|
|
139
|
+
edgePhiDepth: 0.1,
|
|
140
|
+
|
|
141
|
+
enableOIDN: false,
|
|
142
|
+
oidnQuality: 'fast',
|
|
143
|
+
// OIDN as the live-view denoiser, refreshing the accumulating image. Set by choosing 'oidn' in
|
|
144
|
+
// the real-time denoiser list, so that only ever one thing denoises the live view — not by
|
|
145
|
+
// `enableOIDN`, which is the separate question of whether the finished image gets a pass.
|
|
146
|
+
continuousDenoise: false,
|
|
147
|
+
// Lower bound on the gap between cadence denoises. DenoisingManager also floors that gap at a
|
|
148
|
+
// multiple of what the last denoise actually cost, and above ~1024² that is what binds — this
|
|
149
|
+
// value only governs where a denoise is cheap. 8 ms measured 31 refreshes/sec at 512² at an
|
|
150
|
+
// unchanged sample rate; 50 ms measured 18/sec for nothing in return.
|
|
151
|
+
continuousDenoiseInterval: 8,
|
|
152
|
+
// While the view moves, feed OIDN the reprojected history of restarted frames, not one sample.
|
|
153
|
+
oidnTemporalHistory: true,
|
|
154
|
+
|
|
155
|
+
enableUpscaler: false,
|
|
156
|
+
upscalerScale: 2,
|
|
157
|
+
upscalerQuality: 'fast',
|
|
158
|
+
upscalerHdr: true,
|
|
159
|
+
|
|
160
|
+
// ASVGF runs its quality preset whenever it is switched on, so its values are that preset's.
|
|
161
|
+
enableASVGF: false,
|
|
162
|
+
asvgfQualityPreset: 'medium',
|
|
163
|
+
asvgfTemporalAlpha: ASVGF_MEDIUM.temporalAlpha,
|
|
164
|
+
asvgfAtrousIterations: ASVGF_MEDIUM.atrousIterations,
|
|
165
|
+
asvgfPhiColor: ASVGF_MEDIUM.phiColor,
|
|
166
|
+
asvgfPhiNormal: ASVGF_MEDIUM.phiNormal,
|
|
167
|
+
asvgfPhiDepth: ASVGF_MEDIUM.phiDepth,
|
|
168
|
+
asvgfPhiLuminance: ASVGF_MEDIUM.phiLuminance,
|
|
169
|
+
asvgfVarianceBoost: ASVGF_MEDIUM.varianceBoost,
|
|
170
|
+
asvgfMaxAccumFrames: ASVGF_MEDIUM.maxAccumFrames,
|
|
171
|
+
// Must be > 0: the gradient also rejects fireflies before the EMA smears them across
|
|
172
|
+
// ~1/alpha frames. At 0 the denoiser measures ~3x worse than no denoiser at 1 spp.
|
|
173
|
+
asvgfGradientStrength: ASVGF_MEDIUM.gradientStrength,
|
|
174
|
+
asvgfGradientSigmaScale: ASVGF_MEDIUM.gradientSigmaScale,
|
|
175
|
+
asvgfGradientNoiseFloor: ASVGF_MEDIUM.gradientNoiseFloor,
|
|
176
|
+
asvgfDebugMode: 0,
|
|
177
|
+
showAsvgfHeatmap: false,
|
|
178
|
+
|
|
179
|
+
// NRD (ReBLUR port) real-time denoiser — see NRD_DEFAULTS / NRD_QUALITY_PRESETS.
|
|
180
|
+
nrdQualityPreset: 'medium',
|
|
181
|
+
nrdDebugMode: 0,
|
|
182
|
+
};
|
package/src/Stages/EdgeFilter.js
CHANGED
|
@@ -5,7 +5,8 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
|
|
|
5
5
|
import { FloatType, RGBAFormat, LinearFilter, Box2, Vector2 } from 'three';
|
|
6
6
|
import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
7
7
|
import { luminance } from '../TSL/Common.js';
|
|
8
|
-
import {
|
|
8
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
9
|
+
import { ALBEDO_EPS } from './DenoiserSettings.js';
|
|
9
10
|
|
|
10
11
|
// NormalDepth writes depth ≈ 65504 for miss (env/background) rays. This sits below
|
|
11
12
|
// the sentinel and above any real ray distance, so it's a clean hit/miss flag.
|
|
@@ -3,7 +3,7 @@ import { Fn, vec2, vec3, vec4, float, int, uint, ivec2, uvec2, uniform, If,
|
|
|
3
3
|
import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
|
|
4
4
|
import { HalfFloatType, RGBAFormat, NearestFilter, Matrix4, Box2, Vector2 } from 'three';
|
|
5
5
|
import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
6
|
-
import { MAX_STORAGE_TEXTURE_SIZE } from '../
|
|
6
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
7
7
|
import { cameraRayPoint, cameraRayUniforms } from '../TSL/CameraRay.js';
|
|
8
8
|
|
|
9
9
|
/**
|
package/src/Stages/NRD.js
CHANGED
|
@@ -8,9 +8,8 @@ import { createStorageTexture } from '../Processor/StorageTexturePool.js';
|
|
|
8
8
|
import { sanitizeRGB, sanitize1, FP16_MAX } from '../TSL/Common.js';
|
|
9
9
|
import { cameraRayPoint, cameraRayUniforms, isOrthographic } from '../TSL/CameraRay.js';
|
|
10
10
|
import {
|
|
11
|
-
ALBEDO_EPS, GBUFFER_MISS_THRESHOLD as MISS_THRESHOLD,
|
|
12
|
-
|
|
13
|
-
} from '../EngineDefaults.js';
|
|
11
|
+
NRD_DEFAULTS, NRD_HIT_DIST_A, NRD_HIT_DIST_B, ALBEDO_EPS, GBUFFER_MISS_THRESHOLD as MISS_THRESHOLD,
|
|
12
|
+
} from './DenoiserSettings.js';
|
|
14
13
|
|
|
15
14
|
const NRD_EPS = 1e-6;
|
|
16
15
|
const NORMAL_ENCODING_ERROR = 1.5 / 255.0;
|
|
@@ -3,7 +3,8 @@ import { Fn, vec2, vec4, float, int, uint, uvec2, uvec4, uniform, min, storage,
|
|
|
3
3
|
import { RenderTarget, StorageTexture } from 'three/webgpu';
|
|
4
4
|
import { HalfFloatType, RGBAFormat, RedIntegerFormat, UnsignedIntType, NearestFilter, Matrix4, Box2, Vector2 } from 'three';
|
|
5
5
|
import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
6
|
-
import { MAX_STORAGE_TEXTURE_SIZE } from '../
|
|
6
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
7
|
+
import { GBUFFER_MISS_DEPTH } from './DenoiserSettings.js';
|
|
7
8
|
import { Ray, HitInfo, RayTracingMaterial, UVCache } from '../TSL/Struct.js';
|
|
8
9
|
import { traverseBVH } from '../TSL/BVHTraversal.js';
|
|
9
10
|
import { cameraRayOf, cameraRayUniforms } from '../TSL/CameraRay.js';
|
|
@@ -248,7 +249,7 @@ export class NormalDepth extends RenderStage {
|
|
|
248
249
|
|
|
249
250
|
const result = hit.didHit.select(
|
|
250
251
|
vec4( encodedNormal, depth ),
|
|
251
|
-
vec4( 0.0, 0.0, 0.0, float(
|
|
252
|
+
vec4( 0.0, 0.0, 0.0, float( GBUFFER_MISS_DEPTH ) )
|
|
252
253
|
);
|
|
253
254
|
|
|
254
255
|
textureStore(
|
package/src/Stages/PathTracer.js
CHANGED
|
@@ -16,6 +16,7 @@ import { KernelManager } from '../Processor/KernelManager.js';
|
|
|
16
16
|
import { buildGenerateKernel, GENERATE_WG_SIZE } from '../TSL/GenerateKernel.js';
|
|
17
17
|
import { buildExtendKernel, EXTEND_WG_SIZE } from '../TSL/ExtendKernel.js';
|
|
18
18
|
import { buildShadeKernel, SHADE_WG_SIZE } from '../TSL/ShadeKernel.js';
|
|
19
|
+
import { buildVisibilityFoldKernel, buildVisibilityClearKernel } from '../TSL/LightVisibility.js';
|
|
19
20
|
import { buildCompactKernel, buildCompactSubgroupKernel, COMPACT_WG_SIZE } from '../TSL/CompactKernel.js';
|
|
20
21
|
import { buildFinalWriteKernel, FINALWRITE_WG_SIZE } from '../TSL/FinalWriteKernel.js';
|
|
21
22
|
import { buildDebugKernel, DEBUG_WG_SIZE } from '../TSL/DebugKernel.js';
|
|
@@ -25,7 +26,8 @@ import {
|
|
|
25
26
|
buildResetGlobalHistKernel, buildGlobalHistKernel, buildGlobalPrefixKernel, buildGlobalScatterKernel,
|
|
26
27
|
SORT_GLOBAL_WG_SIZE, SORT_GLOBAL_MAX_BINS,
|
|
27
28
|
} from '../TSL/SortGlobalKernels.js';
|
|
28
|
-
import { ENGINE_DEFAULTS
|
|
29
|
+
import { ENGINE_DEFAULTS } from '../EngineDefaults.js';
|
|
30
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
29
31
|
import { ISSUE_CODES } from '../EngineIssues.js';
|
|
30
32
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
31
33
|
import { deviceMemoryGB } from '../Processor/HostMemory.js';
|
|
@@ -40,6 +42,9 @@ export const LIST_WG_SIZE = 256;
|
|
|
40
42
|
|
|
41
43
|
// Resized per bounce iteration, each from its own registered workgroup size. Unregistered entries
|
|
42
44
|
// (the sort passes when _sortMaterials is off) are skipped by setDispatchForCount.
|
|
45
|
+
const PICKED_SHADOW_RAYS = [ 'two', 'one' ];
|
|
46
|
+
const SHADOW_RAY_MODES = [ 'all', ...PICKED_SHADOW_RAYS ];
|
|
47
|
+
|
|
43
48
|
export const BOUNCE_KERNELS = [ 'extend', 'shade', 'connect', 'merge', 'globalHist', 'globalScatter', 'compact', 'compactCopyback', 'lightCopyback' ];
|
|
44
49
|
|
|
45
50
|
export class PathTracer extends PathTracerStage {
|
|
@@ -83,9 +88,10 @@ export class PathTracer extends PathTracerStage {
|
|
|
83
88
|
// CPU sizes per-bounce kernels from last frame's survivor curve; kernels bound on ENTERING_COUNT so over-sizing is safe. (indirect dispatch not viable — three.js doesn't sync compute-written indirect buffers across submissions)
|
|
84
89
|
this._useDynamicDispatch = true;
|
|
85
90
|
|
|
86
|
-
// Global material-coherence sort:
|
|
91
|
+
// Global material-coherence sort: the wavefrontSortMaterials setting, applied per build above 8 materials.
|
|
87
92
|
// Reorders entering rays into material-pure workgroups before Shade; runs under dynamic dispatch
|
|
88
93
|
// (compact reads the unsorted active list, so the survivor set is unchanged). Measured −8% at 1024²/8b.
|
|
94
|
+
this.sortMaterials = options.sortMaterials ?? ENGINE_DEFAULTS.wavefrontSortMaterials;
|
|
89
95
|
this._sortMaterials = false;
|
|
90
96
|
|
|
91
97
|
// Flag-gated off: perf-neutral vs atomic-append and adds a 'subgroups' feature dependency.
|
|
@@ -153,6 +159,9 @@ export class PathTracer extends PathTracerStage {
|
|
|
153
159
|
this._outputsChanged = false;
|
|
154
160
|
// The material layers the kernels were compiled with (_layersToCompile).
|
|
155
161
|
this._compiledLayers = null;
|
|
162
|
+
this._shadowRays = 'all';
|
|
163
|
+
this._compiledPick = null;
|
|
164
|
+
this._learnsVisibility = false;
|
|
156
165
|
|
|
157
166
|
// Integrators other than the path tracer's own, by name (registerIntegrator); the chosen one's instance, or
|
|
158
167
|
// null for plain path tracing, which builds exactly the unidirectional kernels.
|
|
@@ -333,6 +342,44 @@ export class PathTracer extends PathTracerStage {
|
|
|
333
342
|
|
|
334
343
|
}
|
|
335
344
|
|
|
345
|
+
/**
|
|
346
|
+
* Shadow rays a hit for the lamps, sky, sun and emitters: 'all', one per kind; 'two', the strongest and one picked
|
|
347
|
+
* from the rest; 'one', one picked, by unshadowed light and where each kind gets through. Rebuilds the kernels
|
|
348
|
+
* before the next frame; bidirectional integrators ignore it.
|
|
349
|
+
* @param {'all'|'two'|'one'} mode
|
|
350
|
+
*/
|
|
351
|
+
setShadowRays( mode ) {
|
|
352
|
+
|
|
353
|
+
if ( ! SHADOW_RAY_MODES.includes( mode ) ) {
|
|
354
|
+
|
|
355
|
+
log.warn( `shadowRays: unknown mode "${mode}", using 'all'` );
|
|
356
|
+
mode = 'all';
|
|
357
|
+
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if ( this._shadowRays === mode ) return;
|
|
361
|
+
this._shadowRays = mode;
|
|
362
|
+
this._outputsChanged = true;
|
|
363
|
+
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* The lightPick variant to compile, or null for a ray per light kind: also when the scene has no more kinds than the
|
|
368
|
+
* variant traces rays, where it would only add its bookkeeping.
|
|
369
|
+
*/
|
|
370
|
+
_pickedShadowRays() {
|
|
371
|
+
|
|
372
|
+
if ( this._integrator || ! PICKED_SHADOW_RAYS.includes( this._shadowRays ) ) return null;
|
|
373
|
+
const environment = this.enableEnvironment.value > 0;
|
|
374
|
+
const lamps = this.numDirectionalLights.value + this.numAreaLights.value + this.numPointLights.value + this.numSpotLights.value;
|
|
375
|
+
const kinds = Number( lamps > 0 )
|
|
376
|
+
+ Number( environment && this.envTotalSum.value > 0 )
|
|
377
|
+
+ Number( environment && this.hasSun.value > 0 )
|
|
378
|
+
+ Number( this.enableEmissiveTriangleSampling.value > 0 && this.emissiveTriangleCount.value > 0 );
|
|
379
|
+
return kinds > ( this._shadowRays === 'two' ? 2 : 1 ) ? this._shadowRays : null;
|
|
380
|
+
|
|
381
|
+
}
|
|
382
|
+
|
|
336
383
|
get integrator() {
|
|
337
384
|
|
|
338
385
|
return this._integrator?.name ?? 'path';
|
|
@@ -362,6 +409,8 @@ export class PathTracer extends PathTracerStage {
|
|
|
362
409
|
|
|
363
410
|
}
|
|
364
411
|
|
|
412
|
+
if ( PICKED_SHADOW_RAYS.includes( this._shadowRays ) && this._pickedShadowRays() !== this._compiledPick ) this._outputsChanged = true;
|
|
413
|
+
|
|
365
414
|
if ( this._lightBufferRealloc || this._outputsChanged ) {
|
|
366
415
|
|
|
367
416
|
if ( this._kernelManager ) this._kernelManager.dispose();
|
|
@@ -511,6 +560,12 @@ export class PathTracer extends PathTracerStage {
|
|
|
511
560
|
|
|
512
561
|
// An integrator's light subpaths first, through the same pool; every camera chunk then connects to them.
|
|
513
562
|
const integrator = this._integrator?.beginFrame( loopBound ) ? this._integrator : null;
|
|
563
|
+
// A camera move keeps what was learned (it is kept per place in the scene); a repeatable render starts afresh.
|
|
564
|
+
if ( this._learnsVisibility && frameValue === 0 && ( this._pinSeedToFrame || this._lockstep || ! this.cameraChanged ) ) {
|
|
565
|
+
|
|
566
|
+
km.dispatch( 'visibilityClear' );
|
|
567
|
+
|
|
568
|
+
}
|
|
514
569
|
|
|
515
570
|
// Blender-style row-band streaming: the fixed-budget path pool processes the image in bands of ≤ chunkRows
|
|
516
571
|
// rows (one chunk when the frame fits the budget → identical to the pre-chunking path). See spec.
|
|
@@ -650,6 +705,7 @@ export class PathTracer extends PathTracerStage {
|
|
|
650
705
|
|
|
651
706
|
}
|
|
652
707
|
|
|
708
|
+
if ( this._learnsVisibility ) km.dispatch( 'visibilityFold' );
|
|
653
709
|
this._maybeReadbackCounters();
|
|
654
710
|
|
|
655
711
|
// Skip the normalDepth/albedo copies when aux is off — the wavefront didn't write them and
|
|
@@ -1510,6 +1566,11 @@ export class PathTracer extends PathTracerStage {
|
|
|
1510
1566
|
const prevNormalDepth = this.shaderBuilder.prevNormalDepthTexNode;
|
|
1511
1567
|
const writeTex = this.storageTextures.getWriteTextures();
|
|
1512
1568
|
|
|
1569
|
+
const picked = this._pickedShadowRays();
|
|
1570
|
+
this._compiledPick = picked;
|
|
1571
|
+
const learnsVisibility = picked !== null;
|
|
1572
|
+
this._learnsVisibility = learnsVisibility;
|
|
1573
|
+
qm.setVisibilityTable( learnsVisibility );
|
|
1513
1574
|
const counters = qm.getCounters();
|
|
1514
1575
|
|
|
1515
1576
|
// Copy ACTIVE_RAY_COUNT into bounceCounts[currentBounce] for the readback survivor curve.
|
|
@@ -1813,8 +1874,7 @@ export class PathTracer extends PathTracerStage {
|
|
|
1813
1874
|
};
|
|
1814
1875
|
|
|
1815
1876
|
// Material-coherence sort gate (experiment): only worthwhile above a few materials.
|
|
1816
|
-
this._sortMaterials = (
|
|
1817
|
-
&& ( this.materialData?.materialCount ?? 0 ) > 8;
|
|
1877
|
+
this._sortMaterials = this.sortMaterials && ( this.materialData?.materialCount ?? 0 ) > 8;
|
|
1818
1878
|
|
|
1819
1879
|
const extFn = buildExtendKernel( {
|
|
1820
1880
|
bvhBuffer: freshBvh,
|
|
@@ -1945,6 +2005,8 @@ export class PathTracer extends PathTracerStage {
|
|
|
1945
2005
|
bidirectional: this._integrator?.uniforms ?? null,
|
|
1946
2006
|
hitDistanceEncode: this._outputs.get( 'hitDistance' )?.encode ?? null,
|
|
1947
2007
|
materialLayers: this._compiledLayers,
|
|
2008
|
+
shadowRays: picked,
|
|
2009
|
+
cameraWorldMatrix: this.cameraWorldMatrix,
|
|
1948
2010
|
} );
|
|
1949
2011
|
this._kernelManager.register( 'shade',
|
|
1950
2012
|
own( shadeFn() ).compute(
|
|
@@ -1952,6 +2014,12 @@ export class PathTracer extends PathTracerStage {
|
|
|
1952
2014
|
[ SHADE_WG_SIZE, 1, 1 ]
|
|
1953
2015
|
)
|
|
1954
2016
|
);
|
|
2017
|
+
if ( learnsVisibility ) {
|
|
2018
|
+
|
|
2019
|
+
this._kernelManager.register( 'visibilityClear', buildVisibilityClearKernel( { counters } ) );
|
|
2020
|
+
this._kernelManager.register( 'visibilityFold', buildVisibilityFoldKernel( { counters } ) );
|
|
2021
|
+
|
|
2022
|
+
}
|
|
1955
2023
|
|
|
1956
2024
|
// Subgroup prefix-sum variant when supported.
|
|
1957
2025
|
const subgroupsOK = this._useSubgroupCompact
|
|
@@ -20,7 +20,8 @@ import { SceneProcessor } from '../Processor/SceneProcessor.js';
|
|
|
20
20
|
import { LightSerializer } from '../Processor/LightSerializer';
|
|
21
21
|
|
|
22
22
|
// Constants
|
|
23
|
-
import { ENGINE_DEFAULTS as DEFAULT_STATE
|
|
23
|
+
import { ENGINE_DEFAULTS as DEFAULT_STATE } from '../EngineDefaults.js';
|
|
24
|
+
import { TRIANGLE_DATA_LAYOUT } from '../Processor/BufferLayout.js';
|
|
24
25
|
import { TRI_GEO_ROWS, TRI_SHADE_ROWS } from '../TSL/Common.js';
|
|
25
26
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
26
27
|
|
package/src/Stages/Variance.js
CHANGED
|
@@ -4,7 +4,7 @@ import { RenderTarget, TextureNode, StorageTexture } from 'three/webgpu';
|
|
|
4
4
|
import { FloatType, RGBAFormat, LinearFilter, Box2, Vector2 } from 'three';
|
|
5
5
|
import { RenderStage, StageExecutionMode } from '../Pipeline/RenderStage.js';
|
|
6
6
|
import { luminance } from '../TSL/Common.js';
|
|
7
|
-
import { MAX_STORAGE_TEXTURE_SIZE } from '../
|
|
7
|
+
import { MAX_STORAGE_TEXTURE_SIZE } from '../Processor/StorageTexturePool.js';
|
|
8
8
|
|
|
9
9
|
// NaN/±Inf guard: a poisoned luminance would otherwise corrupt the moment EMA forever
|
|
10
10
|
// (mean/meanSq → variance → BilateralFilter sigmaL). NaN (x!=x) → 0, ±Inf → [0,1e7].
|
package/src/TSL/BVHTraversal.js
CHANGED
|
@@ -25,7 +25,10 @@ import {
|
|
|
25
25
|
bool as tslBool,
|
|
26
26
|
} from 'three/tsl';
|
|
27
27
|
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
TRI_MATERIAL_MASK, TRI_SIDE_SHIFT, BVH_LEAF_MARKERS, BVH_MAX_INDEX, BVH_FOLDED_LEAF_MAX,
|
|
30
|
+
TLAS_LEAF_IDENTITY,
|
|
31
|
+
} from '../Processor/BufferLayout.js';
|
|
29
32
|
import { HitInfo } from './Struct.js';
|
|
30
33
|
import {
|
|
31
34
|
getDatafromStorageBuffer, instanceRows, instanceNormalToWorld, unpackTriangleNormal, triangleRow, shadowFlagsSettle
|
package/src/TSL/Common.js
CHANGED
|
@@ -39,7 +39,7 @@ export const FP16_MAX = 65504.0;
|
|
|
39
39
|
export const sanitize1 = ( x, ceiling = 1e7 ) => select( x.equal( x ), x, float( 0.0 ) ).clamp( 0.0, ceiling );
|
|
40
40
|
export const sanitizeRGB = ( c, ceiling = 1e7 ) =>
|
|
41
41
|
vec3( sanitize1( c.x, ceiling ), sanitize1( c.y, ceiling ), sanitize1( c.z, ceiling ) );
|
|
42
|
-
import {
|
|
42
|
+
import { TRI_BLOCKER_SHIFT, TRI_BLOCKER_ALPHA_SHIFT, MATERIAL_DATA_LAYOUT } from '../Processor/BufferLayout.js';
|
|
43
43
|
|
|
44
44
|
export const MATERIAL_SLOTS = MATERIAL_DATA_LAYOUT.SLOTS_PER_MATERIAL;
|
|
45
45
|
export const MATERIAL_SLOT = MATERIAL_DATA_LAYOUT.SLOT;
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
computeDotProductsAniso, instanceRows, instanceNormalToWorld, instancePointToWorld,
|
|
33
33
|
unpackTriangleNormal, triangleRow, SHADOW_END
|
|
34
34
|
} from './Common.js';
|
|
35
|
-
import { TRI_MATERIAL_MASK } from '../
|
|
35
|
+
import { TRI_MATERIAL_MASK } from '../Processor/BufferLayout.js';
|
|
36
36
|
import { getRandomSample1D, getRandomSample2D } from './Random.js';
|
|
37
37
|
import { calculateMaterialPDFFromDots } from './LightsSampling.js';
|
|
38
38
|
import { evaluateMaterialResponseFromDots, evaluateDiffuseTransmission } from './MaterialEvaluation.js';
|