three-gpu-pathtracer 0.0.26 → 0.0.28
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 +4 -2
- package/build/index.module.js +23 -5
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +22 -4
- package/build/index.umd.cjs.map +1 -1
- package/package.json +8 -8
- package/src/core/PathTracingSceneGenerator.js +1 -1
- package/src/core/utils/sceneUpdateUtils.js +2 -1
- package/src/uniforms/EquirectHdrInfoUniform.js +4 -2
- package/src/uniforms/LightsInfoUniformStruct.js +16 -1
- package/src/webgpu/API.md +167 -19
- package/src/webgpu/AtlasTexture.js +32 -12
- package/src/webgpu/EquirectHdrInfoNode.js +97 -46
- package/src/webgpu/LightsInfoNode.js +142 -4
- package/src/webgpu/MegaKernelPathTracer.js +11 -3
- package/src/webgpu/PathTracerBackend.js +174 -21
- package/src/webgpu/TurquinTexture.js +2 -0
- package/src/webgpu/WaveFrontPathTracer.js +169 -71
- package/src/webgpu/WebGPUPathTracer.js +637 -51
- package/src/webgpu/compute/ComputeKernel.js +18 -0
- package/src/webgpu/compute/PathTracerMegaKernel.js +253 -71
- package/src/webgpu/compute/TallySampleCountsKernel.js +10 -10
- package/src/webgpu/compute/UnpackAuxKernel.js +48 -0
- package/src/webgpu/compute/ZeroOutKernel.js +3 -1
- package/src/webgpu/compute/targets.js +55 -0
- package/src/webgpu/compute/wavefront/LogicKernel.js +136 -55
- package/src/webgpu/compute/wavefront/MaterialKernel.js +153 -66
- package/src/webgpu/compute/wavefront/MediumKernel.js +154 -0
- package/src/webgpu/compute/wavefront/PopulatePixelIndicesKernel.js +5 -5
- package/src/webgpu/compute/wavefront/QueueLengthToDispatchKernel.js +5 -5
- package/src/webgpu/compute/wavefront/QueueMediumWalksKernel.js +52 -0
- package/src/webgpu/compute/wavefront/ResetSlotsKernel.js +6 -6
- package/src/webgpu/compute/wavefront/TraceRayKernel.js +11 -9
- package/src/webgpu/compute/wavefront/TraceShadowRayKernel.js +18 -23
- package/src/webgpu/compute/wavefront/structs.js +63 -35
- package/src/webgpu/constants.js +2 -2
- package/src/webgpu/denoise/OIDNDenoiser.js +81 -78
- package/src/webgpu/index.d.ts +79 -6
- package/src/webgpu/materials/GltfCompliantMaterial.js +20 -6
- package/src/webgpu/materials/debug/AuxDebugMaterial.js +54 -0
- package/src/webgpu/nodes/PathtracerBVHComputeData.js +109 -17
- package/src/webgpu/nodes/aux.wgsl.js +61 -0
- package/src/webgpu/nodes/eon.wgsl.js +1 -1
- package/src/webgpu/nodes/lights.wgsl.js +21 -1
- package/src/webgpu/nodes/material.wgsl.js +2 -1
- package/src/webgpu/nodes/medium.wgsl.js +165 -0
- package/src/webgpu/nodes/random.wgsl.js +2 -0
- package/src/webgpu/nodes/sampling.wgsl.js +44 -3
- package/src/webgpu/nodes/structs.wgsl.js +8 -1
- package/src/webgpu/upscale/FSRUpscaler.js +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "three-gpu-pathtracer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.28",
|
|
4
4
|
"description": "Path tracing renderer and utilities for three.js built on top of three-mesh-bvh.",
|
|
5
5
|
"module": "src/index.js",
|
|
6
6
|
"main": "build/index.umd.cjs",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@lookingglass/webxr": "^0.6.0",
|
|
45
45
|
"@monogrid/gainmap-js": "^3.0.5",
|
|
46
|
-
"@pmndrs/upscaler": "^0.
|
|
46
|
+
"@pmndrs/upscaler": "^0.3.0",
|
|
47
47
|
"@types/node": "^24.3.1",
|
|
48
|
-
"@types/three": "^0.
|
|
48
|
+
"@types/three": "^0.186.0",
|
|
49
49
|
"@typescript-eslint/eslint-plugin": "^8.40.0",
|
|
50
50
|
"@vitejs/plugin-basic-ssl": "^2.3.0",
|
|
51
51
|
"@webgpu/types": "^0.1.72",
|
|
@@ -56,22 +56,22 @@
|
|
|
56
56
|
"jsdoc": "^4.0.5",
|
|
57
57
|
"mediabunny": "^1.50.9",
|
|
58
58
|
"node-fetch": "^3.2.9",
|
|
59
|
-
"oidn-
|
|
59
|
+
"oidn-webgpu": "^0.6.0",
|
|
60
60
|
"pixelmatch": "^5.3.0",
|
|
61
61
|
"pngjs": "^6.0.0",
|
|
62
62
|
"process": "^0.11.10",
|
|
63
63
|
"puppeteer": "^24.42.0",
|
|
64
64
|
"rollup": "^2.70.0",
|
|
65
65
|
"simple-git": "^3.10.0",
|
|
66
|
-
"three": "^0.
|
|
67
|
-
"three-mesh-bvh": "^0.9.
|
|
66
|
+
"three": "^0.187.0",
|
|
67
|
+
"three-mesh-bvh": "^0.9.17",
|
|
68
68
|
"typescript": "^5.9.2",
|
|
69
69
|
"vite": "^8.2.2",
|
|
70
70
|
"yargs": "^17.5.1"
|
|
71
71
|
},
|
|
72
72
|
"peerDependencies": {
|
|
73
|
-
"three": ">=0.
|
|
74
|
-
"three-mesh-bvh": ">=0.9.
|
|
73
|
+
"three": ">=0.187.0",
|
|
74
|
+
"three-mesh-bvh": ">=0.9.17",
|
|
75
75
|
"xatlas-web": "^0.1.0"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
@@ -177,7 +177,7 @@ export class PathTracingSceneGenerator {
|
|
|
177
177
|
// generate the geometry
|
|
178
178
|
const result = staticGeometryGenerator.generate( geometry );
|
|
179
179
|
const materials = result.materials;
|
|
180
|
-
let needsMaterialIndexUpdate = result.changeType !== NO_CHANGE || this._materialUuids === null || this._materialUuids.length !== length;
|
|
180
|
+
let needsMaterialIndexUpdate = result.changeType !== NO_CHANGE || this._materialUuids === null || this._materialUuids.length !== materials.length;
|
|
181
181
|
if ( ! needsMaterialIndexUpdate ) {
|
|
182
182
|
|
|
183
183
|
for ( let i = 0, length = materials.length; i < length; i ++ ) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DataTexture, RedFormat, LinearFilter, DataUtils, HalfFloatType,
|
|
1
|
+
import { DataTexture, RedFormat, LinearFilter, DataUtils, HalfFloatType, TextureSource, RepeatWrapping, RGBAFormat, FloatType, ClampToEdgeWrapping } from 'three';
|
|
2
2
|
import { toHalfFloatArray } from '../utils/TextureUtils.js';
|
|
3
3
|
|
|
4
4
|
function binarySearchFindClosestIndexOf( array, targetValue, offset = 0, count = array.length ) {
|
|
@@ -42,7 +42,7 @@ function colorToLuminance( r, g, b ) {
|
|
|
42
42
|
function preprocessEnvMap( envMap, targetType = HalfFloatType ) {
|
|
43
43
|
|
|
44
44
|
const map = envMap.clone();
|
|
45
|
-
map.source = new
|
|
45
|
+
map.source = new TextureSource( { ...map.image } );
|
|
46
46
|
const { width, height, data } = map.image;
|
|
47
47
|
|
|
48
48
|
// TODO: is there a simple way to avoid cloning and adjusting the env map data here?
|
|
@@ -311,6 +311,8 @@ export class EquirectHdrInfoUniform {
|
|
|
311
311
|
|
|
312
312
|
this.totalSum = totalSumValue;
|
|
313
313
|
this.map = map;
|
|
314
|
+
this.cdfMarginal = cdfMarginal;
|
|
315
|
+
this.cdfConditional = cdfConditional;
|
|
314
316
|
|
|
315
317
|
}
|
|
316
318
|
|
|
@@ -2,6 +2,7 @@ import { DataTexture, RGBAFormat, ClampToEdgeWrapping, FloatType, Vector3, Quate
|
|
|
2
2
|
import { bufferToHash } from '../utils/bufferToHash.js';
|
|
3
3
|
|
|
4
4
|
const LIGHT_PIXELS = 6;
|
|
5
|
+
const VISIBLE_TO_CAMERA_OFFSET = 11;
|
|
5
6
|
const RECT_AREA_LIGHT = 0;
|
|
6
7
|
const CIRC_AREA_LIGHT = 1;
|
|
7
8
|
const SPOT_LIGHT = 2;
|
|
@@ -82,7 +83,7 @@ export class LightsInfoUniformStruct {
|
|
|
82
83
|
|
|
83
84
|
type = SPOT_LIGHT;
|
|
84
85
|
|
|
85
|
-
} else if ( l.isDirectionalLight ) {
|
|
86
|
+
} else if ( l.isDirectionalLight || l.isSunLight ) {
|
|
86
87
|
|
|
87
88
|
type = DIR_LIGHT;
|
|
88
89
|
|
|
@@ -207,8 +208,22 @@ export class LightsInfoUniformStruct {
|
|
|
207
208
|
floatArray[ baseIndex + ( index ++ ) ] = target.y;
|
|
208
209
|
floatArray[ baseIndex + ( index ++ ) ] = target.z;
|
|
209
210
|
|
|
211
|
+
} else if ( l.isSunLight ) {
|
|
212
|
+
|
|
213
|
+
// the sun has no target and shines from its position toward the origin
|
|
214
|
+
target.setFromMatrixPosition( l.matrixWorld ).normalize();
|
|
215
|
+
|
|
216
|
+
// sample 3
|
|
217
|
+
// u vector
|
|
218
|
+
floatArray[ baseIndex + ( index ++ ) ] = target.x;
|
|
219
|
+
floatArray[ baseIndex + ( index ++ ) ] = target.y;
|
|
220
|
+
floatArray[ baseIndex + ( index ++ ) ] = target.z;
|
|
221
|
+
|
|
210
222
|
}
|
|
211
223
|
|
|
224
|
+
// whether camera rays see the light
|
|
225
|
+
floatArray[ baseIndex + VISIBLE_TO_CAMERA_OFFSET ] = l.visibleToCameraRays ? 1 : 0;
|
|
226
|
+
|
|
212
227
|
}
|
|
213
228
|
|
|
214
229
|
this.count = lights.length;
|
package/src/webgpu/API.md
CHANGED
|
@@ -17,7 +17,7 @@ Uncorrelated pseudo random samples. Converges slowest but never shows structured
|
|
|
17
17
|
RANDOM_SOBOL: Object
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Sobol low discrepancy samples, scrambled per pixel. Converges faster than `RANDOM_PCG`.
|
|
20
|
+
Sobol low discrepancy samples, scrambled per pixel. Converges faster than `RANDOM_PCG`. The default.
|
|
21
21
|
|
|
22
22
|
### RANDOM_BLUE_DITHER
|
|
23
23
|
|
|
@@ -26,7 +26,7 @@ RANDOM_BLUE_DITHER: Object
|
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
The same Sobol sequence for every pixel, offset by a blue noise dither so early frames read as
|
|
29
|
-
smooth grain rather than clumped noise.
|
|
29
|
+
smooth grain rather than clumped noise.
|
|
30
30
|
|
|
31
31
|
## Transmissive Background Modes
|
|
32
32
|
|
|
@@ -143,7 +143,7 @@ Runs Open Image Denoise over a path traced image. Pass one to
|
|
|
143
143
|
nor the network files become a dependency.
|
|
144
144
|
|
|
145
145
|
```js
|
|
146
|
-
import { initUNetFromURL } from 'oidn-
|
|
146
|
+
import { initUNetFromURL } from 'oidn-webgpu';
|
|
147
147
|
pathTracer.setDenoiser( new OIDNDenoiser( { initUNetFromURL, auxWeightsUrl } ) );
|
|
148
148
|
```
|
|
149
149
|
|
|
@@ -151,6 +151,17 @@ Weights come from the oidn-weights repository, where the "_small" and "_large" v
|
|
|
151
151
|
quality against download size and per tile cost.
|
|
152
152
|
|
|
153
153
|
|
|
154
|
+
### events
|
|
155
|
+
|
|
156
|
+
```js
|
|
157
|
+
// Fired when a pass started by `update` fails, such as the weights failing to download, with the
|
|
158
|
+
// failure as the event's `error`. No other pass starts until a reset.
|
|
159
|
+
{ type: 'error' }
|
|
160
|
+
|
|
161
|
+
// Fired as each tile of a pass finishes, with the fraction of the pass done as `progress`.
|
|
162
|
+
{ type: 'progress' }
|
|
163
|
+
```
|
|
164
|
+
|
|
154
165
|
### .texture
|
|
155
166
|
|
|
156
167
|
```js
|
|
@@ -210,20 +221,17 @@ init( renderer: WebGPURenderer ): void
|
|
|
210
221
|
```
|
|
211
222
|
|
|
212
223
|
|
|
213
|
-
### .setScene
|
|
214
|
-
|
|
215
|
-
```js
|
|
216
|
-
setScene( scene: Scene, camera: Camera ): void
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
|
|
220
224
|
### .update
|
|
221
225
|
|
|
222
226
|
```js
|
|
223
|
-
update(
|
|
227
|
+
update(
|
|
228
|
+
target: Texture,
|
|
229
|
+
aux = null: StorageArrayTexture | null
|
|
230
|
+
): Texture | null
|
|
224
231
|
```
|
|
225
232
|
|
|
226
|
-
|
|
233
|
+
Unpacks the auxiliary buffers the path tracer accumulated and starts a pass. Safe to call
|
|
234
|
+
every frame.
|
|
227
235
|
|
|
228
236
|
|
|
229
237
|
### .denoise
|
|
@@ -261,6 +269,19 @@ the environment afterward require the matching `update*` function. Any change th
|
|
|
261
269
|
the accumulated image restarts it.
|
|
262
270
|
|
|
263
271
|
|
|
272
|
+
### events
|
|
273
|
+
|
|
274
|
+
```js
|
|
275
|
+
// Fired once every pixel has reached `maxSamples` and an attached denoiser has finished. Fires
|
|
276
|
+
// again after a reset, or after `maxSamples` is raised, once the render has caught up.
|
|
277
|
+
{ type: 'complete' }
|
|
278
|
+
|
|
279
|
+
// Fired as the render advances. `stage` is "building", "compiling", "rendering" or "denoising", and
|
|
280
|
+
// `progress` is the fraction of it done, or null when unknown. "rendering" also gives the sample
|
|
281
|
+
// counts as `samples`, reported a few times a second.
|
|
282
|
+
{ type: 'progress' }
|
|
283
|
+
```
|
|
284
|
+
|
|
264
285
|
### .maxBounces
|
|
265
286
|
|
|
266
287
|
```js
|
|
@@ -277,20 +298,40 @@ resolve more indirect light at the cost of speed.
|
|
|
277
298
|
frameBudget: number = 250000
|
|
278
299
|
```
|
|
279
300
|
|
|
280
|
-
Number of path
|
|
301
|
+
Number of path steps dispatched per [WebGPUPathTracer#renderSample](WebGPUPathTracer#renderSample) call,
|
|
281
302
|
independent of resolution. Raising it trades frame rate for convergence speed.
|
|
282
303
|
|
|
283
304
|
|
|
305
|
+
### .frameTime
|
|
306
|
+
|
|
307
|
+
```js
|
|
308
|
+
readonly frameTime: number
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
GPU time in milliseconds of a recent [WebGPUPathTracer#renderSample](WebGPUPathTracer#renderSample) call. Only measured
|
|
312
|
+
when the renderer is created with `trackTimestamp: true`.
|
|
313
|
+
|
|
314
|
+
|
|
284
315
|
### .maxTransparentBounces
|
|
285
316
|
|
|
286
317
|
```js
|
|
287
|
-
maxTransparentBounces: number =
|
|
318
|
+
maxTransparentBounces: number = 15
|
|
288
319
|
```
|
|
289
320
|
|
|
290
321
|
Maximum number of alpha tested surfaces a ray can pass through. Counted separately from
|
|
291
322
|
[WebGPUPathTracer#maxBounces](WebGPUPathTracer#maxBounces) so foliage and cutouts cannot exhaust the bounce budget.
|
|
292
323
|
|
|
293
324
|
|
|
325
|
+
### .maxSubsurfaceBounces
|
|
326
|
+
|
|
327
|
+
```js
|
|
328
|
+
maxSubsurfaceBounces: number = 256
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Maximum number of scatter events a path can take inside a subsurface scattering volume. Counted
|
|
332
|
+
separately from [WebGPUPathTracer#maxBounces](WebGPUPathTracer#maxBounces). Paths that reach it end, darkening dense volumes.
|
|
333
|
+
|
|
334
|
+
|
|
294
335
|
### .maxSamples
|
|
295
336
|
|
|
296
337
|
```js
|
|
@@ -303,6 +344,16 @@ render has stopped, so it has no effect while this is `0`.
|
|
|
303
344
|
> [!NOTE]
|
|
304
345
|
> `0` renders indefinitely.
|
|
305
346
|
|
|
347
|
+
### .complete
|
|
348
|
+
|
|
349
|
+
```js
|
|
350
|
+
complete: boolean
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Whether every pixel has reached [WebGPUPathTracer#maxSamples](WebGPUPathTracer#maxSamples) and an attached denoiser
|
|
354
|
+
has finished, as of the last measurement. Always false while rendering indefinitely.
|
|
355
|
+
|
|
356
|
+
|
|
306
357
|
### .transmissiveBackground
|
|
307
358
|
|
|
308
359
|
```js
|
|
@@ -395,6 +446,17 @@ readonly lowResMode: boolean
|
|
|
395
446
|
Whether the tracer is currently rendering the low resolution preview.
|
|
396
447
|
|
|
397
448
|
|
|
449
|
+
### .compiling
|
|
450
|
+
|
|
451
|
+
```js
|
|
452
|
+
readonly compiling: boolean
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Whether the kernels are compiling, such as after the scene or material changes. Nothing new
|
|
456
|
+
renders until they finish and the canvas keeps the last frame, so an app may draw its own
|
|
457
|
+
preview in the meantime.
|
|
458
|
+
|
|
459
|
+
|
|
398
460
|
### .textureAtlas
|
|
399
461
|
|
|
400
462
|
```js
|
|
@@ -410,13 +472,13 @@ The atlas every scene texture is packed into for the kernels to sample.
|
|
|
410
472
|
minSamples: number = 1
|
|
411
473
|
```
|
|
412
474
|
|
|
413
|
-
|
|
475
|
+
Average samples per pixel the full resolution render must reach before it is faded in.
|
|
414
476
|
|
|
415
477
|
|
|
416
478
|
### .renderDelay
|
|
417
479
|
|
|
418
480
|
```js
|
|
419
|
-
renderDelay: number =
|
|
481
|
+
renderDelay: number = 16
|
|
420
482
|
```
|
|
421
483
|
|
|
422
484
|
Milliseconds to show the low resolution preview for after a reset.
|
|
@@ -425,7 +487,7 @@ Milliseconds to show the low resolution preview for after a reset.
|
|
|
425
487
|
### .fadeDuration
|
|
426
488
|
|
|
427
489
|
```js
|
|
428
|
-
fadeDuration: number =
|
|
490
|
+
fadeDuration: number = 250
|
|
429
491
|
```
|
|
430
492
|
|
|
431
493
|
Milliseconds taken to cross fade from the preview to the full render.
|
|
@@ -446,7 +508,39 @@ Whether to render a low resolution preview while the camera is moving.
|
|
|
446
508
|
lowResScale: number = 0.1
|
|
447
509
|
```
|
|
448
510
|
|
|
449
|
-
Resolution of the low resolution preview, as a fraction of the render size.
|
|
511
|
+
Resolution of the low resolution preview, as a fraction of the render size. Adjusted when
|
|
512
|
+
[WebGPUPathTracer#adaptiveDynamicRes](WebGPUPathTracer#adaptiveDynamicRes) is set. The preview never has more pixels than a
|
|
513
|
+
frame of [WebGPUPathTracer#frameBudget](WebGPUPathTracer#frameBudget) can render.
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
### .adaptiveDynamicRes
|
|
517
|
+
|
|
518
|
+
```js
|
|
519
|
+
adaptiveDynamicRes: boolean = true
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
Whether [WebGPUPathTracer#lowResScale](WebGPUPathTracer#lowResScale) is adjusted to the pixels a frame of
|
|
523
|
+
[WebGPUPathTracer#frameBudget](WebGPUPathTracer#frameBudget) can render.
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
### .adaptiveFrameBudget
|
|
527
|
+
|
|
528
|
+
```js
|
|
529
|
+
adaptiveFrameBudget: boolean = true
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
Whether [WebGPUPathTracer#frameBudget](WebGPUPathTracer#frameBudget) is adjusted to keep each
|
|
533
|
+
[WebGPUPathTracer#renderSample](WebGPUPathTracer#renderSample) call near [WebGPUPathTracer#targetFrameTime](WebGPUPathTracer#targetFrameTime) of
|
|
534
|
+
GPU time. Requires a renderer created with `trackTimestamp: true`.
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
### .targetFrameTime
|
|
538
|
+
|
|
539
|
+
```js
|
|
540
|
+
targetFrameTime: number = 16
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
GPU time in milliseconds per frame targeted by [WebGPUPathTracer#adaptiveFrameBudget](WebGPUPathTracer#adaptiveFrameBudget).
|
|
450
544
|
|
|
451
545
|
|
|
452
546
|
### .renderScale
|
|
@@ -469,6 +563,27 @@ Whether to track the canvas size automatically. Set to `false` to drive the rend
|
|
|
469
563
|
size with [WebGPUPathTracer#setSize](WebGPUPathTracer#setSize).
|
|
470
564
|
|
|
471
565
|
|
|
566
|
+
### .renderToCanvas
|
|
567
|
+
|
|
568
|
+
```js
|
|
569
|
+
renderToCanvas: boolean = true
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
Whether [WebGPUPathTracer#renderSample](WebGPUPathTracer#renderSample) draws the result to the current render
|
|
573
|
+
target, the canvas by default. Set to `false` to only accumulate, as when baking to a
|
|
574
|
+
texture read through [WebGPUPathTracer#target](WebGPUPathTracer#target).
|
|
575
|
+
|
|
576
|
+
|
|
577
|
+
### .asyncCompile
|
|
578
|
+
|
|
579
|
+
```js
|
|
580
|
+
asyncCompile: boolean = false
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
Whether to compile the kernels asynchronously so a compile doesn't stall the page. Nothing
|
|
584
|
+
new renders while [WebGPUPathTracer#compiling](WebGPUPathTracer#compiling) is true.
|
|
585
|
+
|
|
586
|
+
|
|
472
587
|
### .generateMissingAttributes
|
|
473
588
|
|
|
474
589
|
```js
|
|
@@ -539,7 +654,8 @@ setDenoiser( denoiser: OIDNDenoiser | null ): void
|
|
|
539
654
|
```
|
|
540
655
|
|
|
541
656
|
Attaches a denoiser, run once the render settles and displayed in place of the raw image.
|
|
542
|
-
Settings live on the instance. Pass null to remove it.
|
|
657
|
+
Settings live on the instance. Pass null to remove it. The render restarts when the auxiliary
|
|
658
|
+
buffers it needs are added or dropped.
|
|
543
659
|
|
|
544
660
|
|
|
545
661
|
### .setUpscaler
|
|
@@ -564,6 +680,28 @@ against. Call this once, then use the `update*` functions for later changes.
|
|
|
564
680
|
> [!NOTE]
|
|
565
681
|
> Geometry BVHs are built synchronously, so this blocks for large scenes.
|
|
566
682
|
|
|
683
|
+
### .setBVHWorker
|
|
684
|
+
|
|
685
|
+
```js
|
|
686
|
+
setBVHWorker( WorkerConstructor: function ): void
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
Sets the worker class [WebGPUPathTracer#setSceneAsync](WebGPUPathTracer#setSceneAsync) builds the mesh geometry BVHs
|
|
690
|
+
with, such as `GenerateMeshBVHWorker` from three-mesh-bvh. Several are created and disposed
|
|
691
|
+
per call so geometries build in parallel.
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
### .setSceneAsync
|
|
695
|
+
|
|
696
|
+
```js
|
|
697
|
+
async setSceneAsync( scene: Scene, camera: Camera ): Promise<void>
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
Like [WebGPUPathTracer#setScene](WebGPUPathTracer#setScene) but builds the mesh geometry BVHs in the workers set
|
|
701
|
+
with [WebGPUPathTracer#setBVHWorker](WebGPUPathTracer#setBVHWorker) so the page is not blocked. Skinned meshes are
|
|
702
|
+
still built synchronously.
|
|
703
|
+
|
|
704
|
+
|
|
567
705
|
### .setRandom
|
|
568
706
|
|
|
569
707
|
```js
|
|
@@ -708,6 +846,16 @@ Draws a heatmap of the per pixel sample counts, for spotting pixels that converg
|
|
|
708
846
|
> Measures on every call and draws with the previous result, since the readback lands a
|
|
709
847
|
> frame later.
|
|
710
848
|
|
|
849
|
+
### .renderAuxBuffer
|
|
850
|
+
|
|
851
|
+
```js
|
|
852
|
+
renderAuxBuffer( buffer = 'albedo': 'albedo' | 'normal' ): void
|
|
853
|
+
```
|
|
854
|
+
|
|
855
|
+
Draws the albedo or normal auxiliary buffer accumulated for the denoiser, for checking what
|
|
856
|
+
it is given. Nothing is drawn until a denoiser that uses them is attached.
|
|
857
|
+
|
|
858
|
+
|
|
711
859
|
### .dispose
|
|
712
860
|
|
|
713
861
|
```js
|
|
@@ -6,10 +6,11 @@ import {
|
|
|
6
6
|
NoBlending,
|
|
7
7
|
Color,
|
|
8
8
|
Vector4,
|
|
9
|
+
Matrix3,
|
|
9
10
|
} from 'three/webgpu';
|
|
10
11
|
|
|
11
|
-
const MAX_TEXTURE_SIZE = 4096;
|
|
12
12
|
const _prevClearColor = new Color();
|
|
13
|
+
const _prevMatrix = new Matrix3();
|
|
13
14
|
|
|
14
15
|
function getTextureHash( texture ) {
|
|
15
16
|
|
|
@@ -241,9 +242,9 @@ export class AtlasTexture {
|
|
|
241
242
|
|
|
242
243
|
}
|
|
243
244
|
|
|
244
|
-
// calculate the maximum dimension of the atlas
|
|
245
|
+
// calculate the maximum dimension of the atlas, up to what the device allows
|
|
245
246
|
let maxDim = textures.reduce( ( v, t ) => Math.max( v, t.width, t.height ), 1 );
|
|
246
|
-
maxDim = Math.min(
|
|
247
|
+
maxDim = Math.min( renderer.backend.device.limits.maxTextureDimension2D, maxDim );
|
|
247
248
|
|
|
248
249
|
const width = maxDim;
|
|
249
250
|
const height = maxDim;
|
|
@@ -438,21 +439,40 @@ export class AtlasTexture {
|
|
|
438
439
|
for ( let i = 0, l = textures.length; i < l; i ++ ) {
|
|
439
440
|
|
|
440
441
|
const { x, y, w, h, page } = placements[ i ];
|
|
441
|
-
|
|
442
|
-
// Clone the source so we get an independent texture handle
|
|
443
|
-
const texture = textures[ i ].clone();
|
|
444
|
-
texture.matrixAutoUpdate = false;
|
|
445
|
-
texture.matrix.identity();
|
|
446
|
-
|
|
447
|
-
quadMesh.material.map = texture;
|
|
442
|
+
const texture = textures[ i ];
|
|
448
443
|
|
|
449
444
|
// three.js uses the render target viewport / scissor
|
|
450
445
|
renderTarget.viewport.set( x, y, w, h );
|
|
451
446
|
renderTarget.scissor.set( x, y, w, h );
|
|
452
447
|
renderer.setRenderTarget( renderTarget, page );
|
|
453
|
-
quadMesh.render( renderer );
|
|
454
448
|
|
|
455
|
-
texture.
|
|
449
|
+
if ( texture.isRenderTargetTexture ) {
|
|
450
|
+
|
|
451
|
+
// a render target's content only lives on the GPU, so draw it directly
|
|
452
|
+
const prevAutoUpdate = texture.matrixAutoUpdate;
|
|
453
|
+
_prevMatrix.copy( texture.matrix );
|
|
454
|
+
texture.matrix.identity();
|
|
455
|
+
texture.matrixAutoUpdate = false;
|
|
456
|
+
|
|
457
|
+
quadMesh.material.map = texture;
|
|
458
|
+
quadMesh.render( renderer );
|
|
459
|
+
|
|
460
|
+
texture.matrixAutoUpdate = prevAutoUpdate;
|
|
461
|
+
texture.matrix.copy( _prevMatrix );
|
|
462
|
+
|
|
463
|
+
} else {
|
|
464
|
+
|
|
465
|
+
// Clone the source so we get an independent texture handle
|
|
466
|
+
const clone = texture.clone();
|
|
467
|
+
clone.matrixAutoUpdate = false;
|
|
468
|
+
clone.matrix.identity();
|
|
469
|
+
|
|
470
|
+
quadMesh.material.map = clone;
|
|
471
|
+
quadMesh.render( renderer );
|
|
472
|
+
|
|
473
|
+
clone.dispose();
|
|
474
|
+
|
|
475
|
+
}
|
|
456
476
|
|
|
457
477
|
}
|
|
458
478
|
|