rayzee 5.4.1 → 5.4.3
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/dist/rayzee.es.js +2211 -2148
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +42 -42
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/PathTracerApp.js +87 -13
- package/src/Processor/AssetLoader.js +50 -24
- package/src/Processor/GeometryExtractor.js +19 -2
- package/src/Processor/createRenderTargetHelper.js +41 -14
- package/src/Stages/AdaptiveSampling.js +7 -0
- package/src/Stages/PathTracer.js +13 -0
- package/src/TSL/BVHTraversal.js +19 -11
- package/src/TSL/LightsDirect.js +13 -0
- package/src/TSL/TextureSampling.js +1 -1
- package/src/managers/MaterialDataManager.js +93 -3
|
@@ -9,9 +9,16 @@
|
|
|
9
9
|
|
|
10
10
|
import { StorageInstancedBufferAttribute } from 'three/webgpu';
|
|
11
11
|
import { storage } from 'three/tsl';
|
|
12
|
-
import {
|
|
12
|
+
import { MATERIAL_DATA_LAYOUT as M, TRIANGLE_DATA_LAYOUT as T } from '../EngineDefaults.js';
|
|
13
13
|
|
|
14
14
|
const PIXELS_PER_MATERIAL = M.SLOTS_PER_MATERIAL;
|
|
15
|
+
// Per-triangle float offsets used by _patchTriangleSideForMaterial / _patchTriangleBlockerForMaterial.
|
|
16
|
+
const TRI_MAT_IDX_OFFSET = T.UV_C_MAT_OFFSET + 2; // uvData2.z in shader
|
|
17
|
+
const TRI_SIDE_OFFSET = T.NORMAL_C_OFFSET + 3; // normalCData.w in shader
|
|
18
|
+
const TRI_BLOCKER_OFFSET = T.NORMAL_A_OFFSET + 3; // nA.w in shader (opaque-blocker fast path)
|
|
19
|
+
|
|
20
|
+
// Material properties that affect the shadow-ray opaque-blocker flag.
|
|
21
|
+
const BLOCKER_PROPS = new Set( [ 'transmission', 'transparent', 'opacity', 'alphaMode' ] );
|
|
15
22
|
|
|
16
23
|
export class MaterialDataManager {
|
|
17
24
|
|
|
@@ -41,7 +48,7 @@ export class MaterialDataManager {
|
|
|
41
48
|
|
|
42
49
|
/**
|
|
43
50
|
* Optional callbacks set by the owning stage.
|
|
44
|
-
* @type {{ onReset?: Function, onFeaturesChanged?: Function }}
|
|
51
|
+
* @type {{ onReset?: Function, onFeaturesChanged?: Function, getTriangleData?: Function, onTriangleDataChanged?: Function }}
|
|
45
52
|
*/
|
|
46
53
|
this.callbacks = {};
|
|
47
54
|
|
|
@@ -275,7 +282,11 @@ export class MaterialDataManager {
|
|
|
275
282
|
case 'clearcoat': data[ stride + M.CLEARCOAT ] = value; break;
|
|
276
283
|
case 'clearcoatRoughness': data[ stride + M.CLEARCOAT_ROUGHNESS ] = value; break;
|
|
277
284
|
case 'opacity': data[ stride + M.OPACITY ] = value; break;
|
|
278
|
-
case 'side': data[ stride + M.SIDE ] = value;
|
|
285
|
+
case 'side': data[ stride + M.SIDE ] = value;
|
|
286
|
+
// Side is also mirrored into per-triangle data (NORMAL_C.w) so BVH
|
|
287
|
+
// traversal can do side culling without reading the material buffer.
|
|
288
|
+
this._patchTriangleSideForMaterial( materialIndex, value );
|
|
289
|
+
break;
|
|
279
290
|
case 'transparent': data[ stride + M.TRANSPARENT ] = value; break;
|
|
280
291
|
case 'alphaTest': data[ stride + M.ALPHA_TEST ] = value; break;
|
|
281
292
|
case 'alphaMode': data[ stride + M.ALPHA_MODE ] = value; break;
|
|
@@ -304,6 +315,13 @@ export class MaterialDataManager {
|
|
|
304
315
|
|
|
305
316
|
this.materialStorageAttr.needsUpdate = true;
|
|
306
317
|
|
|
318
|
+
// Recompute triangle-data opaque-blocker flag when any input to it changes.
|
|
319
|
+
if ( BLOCKER_PROPS.has( property ) ) {
|
|
320
|
+
|
|
321
|
+
this._recomputeOpaqueBlockerForMaterial( materialIndex );
|
|
322
|
+
|
|
323
|
+
}
|
|
324
|
+
|
|
307
325
|
const featureProperties = [ 'transmission', 'clearcoat', 'sheen', 'iridescence', 'dispersion', 'transparent', 'opacity', 'alphaTest' ];
|
|
308
326
|
if ( featureProperties.includes( property ) ) {
|
|
309
327
|
|
|
@@ -414,6 +432,10 @@ export class MaterialDataManager {
|
|
|
414
432
|
data[ stride + M.CLEARCOAT_ROUGHNESS ] = materialData.clearcoatRoughness ?? 0;
|
|
415
433
|
data[ stride + M.OPACITY ] = materialData.opacity ?? 1;
|
|
416
434
|
data[ stride + M.SIDE ] = materialData.side ?? 0;
|
|
435
|
+
// Mirror side into per-triangle data so BVH traversal avoids a material-buffer read.
|
|
436
|
+
this._patchTriangleSideForMaterial( materialIndex, materialData.side ?? 0 );
|
|
437
|
+
// Recompute shadow-ray opaque-blocker flag (reads alphaMode/transparent/transmission/opacity from buffer).
|
|
438
|
+
this._recomputeOpaqueBlockerForMaterial( materialIndex );
|
|
417
439
|
data[ stride + M.TRANSPARENT ] = materialData.transparent ?? 0;
|
|
418
440
|
data[ stride + M.ALPHA_TEST ] = materialData.alphaTest ?? 0;
|
|
419
441
|
data[ stride + M.ALPHA_MODE ] = materialData.alphaMode ?? 0;
|
|
@@ -657,6 +679,74 @@ export class MaterialDataManager {
|
|
|
657
679
|
|
|
658
680
|
}
|
|
659
681
|
|
|
682
|
+
/**
|
|
683
|
+
* Rewrite the per-triangle `side` flag (NORMAL_C.w) for every triangle whose
|
|
684
|
+
* materialIndex matches. Linear over triangles because there's no reverse
|
|
685
|
+
* index — side edits are a rare UI action so the scan cost is acceptable.
|
|
686
|
+
* @private
|
|
687
|
+
*/
|
|
688
|
+
/**
|
|
689
|
+
* Re-derive the shadow-ray opaque-blocker flag for a material from its
|
|
690
|
+
* current buffer values and patch NORMAL_A.w on every matching triangle.
|
|
691
|
+
* Kept in sync with the blocker definition in GeometryExtractor.
|
|
692
|
+
* @private
|
|
693
|
+
*/
|
|
694
|
+
_recomputeOpaqueBlockerForMaterial( materialIndex ) {
|
|
695
|
+
|
|
696
|
+
const matBuf = this.materialStorageAttr?.array;
|
|
697
|
+
if ( ! matBuf ) return;
|
|
698
|
+
|
|
699
|
+
const matStride = materialIndex * M.FLOATS_PER_MATERIAL;
|
|
700
|
+
const alphaMode = matBuf[ matStride + M.ALPHA_MODE ] | 0;
|
|
701
|
+
const transparent = matBuf[ matStride + M.TRANSPARENT ] | 0;
|
|
702
|
+
const transmission = matBuf[ matStride + M.TRANSMISSION ] || 0;
|
|
703
|
+
const opacity = matBuf[ matStride + M.OPACITY ] ?? 1;
|
|
704
|
+
const isOpaqueBlocker = ( alphaMode === 0 && transparent === 0 && transmission === 0 && opacity >= 1 ) ? 1.0 : 0.0;
|
|
705
|
+
|
|
706
|
+
this._patchTriangleFlagForMaterial( materialIndex, TRI_BLOCKER_OFFSET, isOpaqueBlocker );
|
|
707
|
+
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Generic helper: patch a single per-triangle float at `triOffset` for every
|
|
712
|
+
* triangle whose materialIndex matches, then fire onTriangleDataChanged.
|
|
713
|
+
* @private
|
|
714
|
+
*/
|
|
715
|
+
_patchTriangleFlagForMaterial( materialIndex, triOffset, value ) {
|
|
716
|
+
|
|
717
|
+
const triInfo = this.callbacks.getTriangleData?.();
|
|
718
|
+
const triData = triInfo?.array;
|
|
719
|
+
const triCount = triInfo?.count | 0;
|
|
720
|
+
if ( ! triData || triCount === 0 ) return;
|
|
721
|
+
|
|
722
|
+
const stride = T.FLOATS_PER_TRIANGLE;
|
|
723
|
+
let patched = 0;
|
|
724
|
+
for ( let i = 0; i < triCount; i ++ ) {
|
|
725
|
+
|
|
726
|
+
const base = i * stride;
|
|
727
|
+
if ( triData[ base + TRI_MAT_IDX_OFFSET ] === materialIndex ) {
|
|
728
|
+
|
|
729
|
+
triData[ base + triOffset ] = value;
|
|
730
|
+
patched ++;
|
|
731
|
+
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if ( patched > 0 && this.callbacks.onTriangleDataChanged ) {
|
|
737
|
+
|
|
738
|
+
this.callbacks.onTriangleDataChanged();
|
|
739
|
+
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
_patchTriangleSideForMaterial( materialIndex, sideValue ) {
|
|
745
|
+
|
|
746
|
+
this._patchTriangleFlagForMaterial( materialIndex, TRI_SIDE_OFFSET, sideValue );
|
|
747
|
+
|
|
748
|
+
}
|
|
749
|
+
|
|
660
750
|
// ===== DISPOSAL =====
|
|
661
751
|
|
|
662
752
|
dispose() {
|