rayzee 7.31.0 → 8.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.
Files changed (53) hide show
  1. package/README.md +164 -0
  2. package/dist/rayzee.es.js +6547 -4334
  3. package/dist/rayzee.umd.js +122 -73
  4. package/package.json +1 -1
  5. package/src/EngineDefaults.js +168 -13
  6. package/src/EngineIssues.js +6 -0
  7. package/src/PathTracerApp.js +128 -20
  8. package/src/Processor/ArchiveReader.js +538 -0
  9. package/src/Processor/AssetLoader.js +357 -22
  10. package/src/Processor/BVHBuilder.js +48 -32
  11. package/src/Processor/BVHRefitter.js +244 -99
  12. package/src/Processor/ChunkedRecords.js +302 -0
  13. package/src/Processor/EmissiveTriangleBuilder.js +48 -21
  14. package/src/Processor/GeometryExtractor.js +577 -92
  15. package/src/Processor/HostMemory.js +222 -0
  16. package/src/Processor/InstanceTable.js +548 -97
  17. package/src/Processor/PBRT/EqualAreaOctahedral.js +173 -0
  18. package/src/Processor/PBRT/LoopSubdivision.js +240 -0
  19. package/src/Processor/PBRT/PBRTCurves.js +249 -0
  20. package/src/Processor/PBRT/PBRTMath.js +28 -0
  21. package/src/Processor/PBRT/PBRTParser.js +187 -41
  22. package/src/Processor/PBRT/PBRTSceneBuilder.js +659 -34
  23. package/src/Processor/PBRT/PBRTTokenizer.js +205 -65
  24. package/src/Processor/PBRT/index.js +306 -45
  25. package/src/Processor/PackedRayBuffer.js +29 -18
  26. package/src/Processor/ParallelBVHBuilder.js +9 -8
  27. package/src/Processor/QueueManager.js +5 -3
  28. package/src/Processor/SceneProcessor.js +1063 -366
  29. package/src/Processor/TLASBuilder.js +546 -201
  30. package/src/Processor/TextureCreator.js +11 -9
  31. package/src/Processor/VRAMTracker.js +12 -3
  32. package/src/Processor/Workers/BVHRefitWorker.js +16 -11
  33. package/src/Processor/Workers/BVHWorker.js +12 -12
  34. package/src/Processor/Workers/TLASWorker.js +37 -0
  35. package/src/Stages/NormalDepth.js +6 -2
  36. package/src/Stages/PathTracer.js +5 -5
  37. package/src/Stages/PathTracerStage.js +163 -41
  38. package/src/TSL/BVHTraversal.js +208 -90
  39. package/src/TSL/Common.js +135 -2
  40. package/src/TSL/Displacement.js +21 -11
  41. package/src/TSL/EmissiveSampling.js +49 -25
  42. package/src/TSL/ExtendKernel.js +3 -2
  43. package/src/TSL/LightBVHSampling.js +7 -4
  44. package/src/TSL/LightsDirect.js +30 -29
  45. package/src/TSL/ShadeKernel.js +8 -6
  46. package/src/TSL/Struct.js +3 -0
  47. package/src/TSL/TextureSampling.js +24 -9
  48. package/src/TSL/patches.js +128 -3
  49. package/src/index.js +3 -0
  50. package/src/managers/AnimationManager.js +86 -76
  51. package/src/managers/CameraManager.js +11 -0
  52. package/src/managers/MaterialDataManager.js +29 -23
  53. package/src/managers/TransformManager.js +9 -192
@@ -5,6 +5,21 @@ import { createLogger, fmt } from '../utils/Logger.js';
5
5
 
6
6
  const log = createLogger( 'bvh' );
7
7
 
8
+ // Inline copies of EngineDefaults.BVH_LEAF_MARKERS / bvhIndexView — this module also runs inside
9
+ // a worker, where importing Constants is not safe. Keep in step with EngineDefaults.js.
10
+ // Index fields are u32 BIT PATTERNS, never float values: as floats they round past 2^24.
11
+ const TRIANGLE_LEAF = 0x40000000;
12
+ const FRONTIER_LEAF = 0x40000002;
13
+ const indexView = f32 => new Uint32Array( f32.buffer, f32.byteOffset, f32.length );
14
+ const BVH_MAX_INDEX = 0x40000000;
15
+
16
+ function assertFits( count, what ) {
17
+
18
+ if ( count >= BVH_MAX_INDEX ) throw new RangeError( `${what} is ${count}, at or past the BVH index limit of ${BVH_MAX_INDEX}` );
19
+ return count;
20
+
21
+ }
22
+
8
23
  // Injected, not imported: this module also runs inside the worker, and `?worker&inline`
9
24
  // would embed a second copy of BVHWorker's source there.
10
25
  let createBVHWorker = null;
@@ -19,19 +34,18 @@ export function setBVHWorkerFactory( factory ) {
19
34
  // Cannot import Constants.js because BVHBuilder runs inside BVHWorker
20
35
  // where `window` (used elsewhere in Constants.js) is not defined.
21
36
  const TRIANGLE_DATA_LAYOUT = {
22
- FLOATS_PER_TRIANGLE: 32,
37
+ FLOATS_PER_TRIANGLE: 20,
23
38
  POSITION_A_OFFSET: 0,
24
39
  POSITION_B_OFFSET: 4,
25
- POSITION_C_OFFSET: 8,
26
- NORMAL_A_OFFSET: 12,
27
- NORMAL_B_OFFSET: 16,
28
- NORMAL_C_OFFSET: 20,
29
- UV_AB_OFFSET: 24,
30
- UV_C_MAT_OFFSET: 28 // vec4: uvC.x, uvC.y, materialIndex, meshIndex
40
+ POSITION_C_OFFSET: 8
31
41
  };
32
42
 
33
43
  const FPT = TRIANGLE_DATA_LAYOUT.FLOATS_PER_TRIANGLE;
34
44
 
45
+ // The record buffer is uint; positions are f32 in it. Views share the memory, no copy.
46
+ const floatView = ( data ) => data instanceof Float32Array
47
+ ? data : new Float32Array( data.buffer, data.byteOffset, data.length );
48
+
35
49
  class BVHNode {
36
50
 
37
51
  constructor() {
@@ -215,7 +229,7 @@ export class BVHBuilder {
215
229
  initializeTriangleArrays() {
216
230
 
217
231
  const n = this.totalTriangles;
218
- const src = this.triangles;
232
+ const src = floatView( this.triangles );
219
233
  const PA = TRIANGLE_DATA_LAYOUT.POSITION_A_OFFSET;
220
234
  const PB = TRIANGLE_DATA_LAYOUT.POSITION_B_OFFSET;
221
235
  const PC = TRIANGLE_DATA_LAYOUT.POSITION_C_OFFSET;
@@ -679,7 +693,7 @@ export class BVHBuilder {
679
693
  // Phase 6: Create reordered triangle data from final index order
680
694
  const reorderStart = performance.now();
681
695
  const triSrc = this.triangles;
682
- const reordered = reorderTarget || new Float32Array( n * FPT );
696
+ const reordered = reorderTarget || new triSrc.constructor( n * FPT );
683
697
  for ( let i = 0; i < n; i ++ ) {
684
698
 
685
699
  const srcOff = this.indices[ i ] * FPT;
@@ -1580,7 +1594,9 @@ export class BVHBuilder {
1580
1594
  // Inner: [leftMin.xyz, leftChild] [leftMax.xyz, rightChild] [rightMin.xyz, 0] [rightMax.xyz, 0]
1581
1595
  // Leaf: [triOffset, triCount, 0, -1] [0,0,0,0] [0,0,0,0] [0,0,0,0]
1582
1596
  const FLOATS_PER_NODE = 16;
1597
+ assertFits( nodes.length, 'BLAS node count' );
1583
1598
  const data = new Float32Array( nodes.length * FLOATS_PER_NODE );
1599
+ const idx = indexView( data );
1584
1600
 
1585
1601
  for ( let i = 0; i < nodes.length; i ++ ) {
1586
1602
 
@@ -1596,12 +1612,12 @@ export class BVHBuilder {
1596
1612
  data[ o ] = left.minX;
1597
1613
  data[ o + 1 ] = left.minY;
1598
1614
  data[ o + 2 ] = left.minZ;
1599
- data[ o + 3 ] = left._flatIndex;
1615
+ idx[ o + 3 ] = left._flatIndex;
1600
1616
 
1601
1617
  data[ o + 4 ] = left.maxX;
1602
1618
  data[ o + 5 ] = left.maxY;
1603
1619
  data[ o + 6 ] = left.maxZ;
1604
- data[ o + 7 ] = right._flatIndex;
1620
+ idx[ o + 7 ] = right._flatIndex;
1605
1621
 
1606
1622
  data[ o + 8 ] = right.minX;
1607
1623
  data[ o + 9 ] = right.minY;
@@ -1615,11 +1631,10 @@ export class BVHBuilder {
1615
1631
 
1616
1632
  } else {
1617
1633
 
1618
- // Leaf node: triOffset, triCount in vec4(0), marked by leftChild = -1
1619
- data[ o ] = node.triangleOffset;
1620
- data[ o + 1 ] = node.triangleCount;
1634
+ idx[ o ] = node.triangleOffset;
1635
+ idx[ o + 1 ] = node.triangleCount;
1621
1636
  // data[o+2] = 0 (padding)
1622
- data[ o + 3 ] = - 1; // Leaf marker
1637
+ idx[ o + 3 ] = TRIANGLE_LEAF;
1623
1638
 
1624
1639
  }
1625
1640
 
@@ -1630,7 +1645,7 @@ export class BVHBuilder {
1630
1645
  }
1631
1646
 
1632
1647
  /**
1633
- * Flatten BVH tree marking frontier leaves with -2 sentinel.
1648
+ * Flatten BVH tree marking frontier leaves with the frontier tag.
1634
1649
  * Returns the flat data and a frontier map for assembly.
1635
1650
  * @param {BVHNode} root
1636
1651
  * @returns {{ flatData: Float32Array, frontierMap: Array<{taskId: number, flatIndex: number}> }}
@@ -1653,8 +1668,10 @@ export class BVHBuilder {
1653
1668
  }
1654
1669
 
1655
1670
  // Second pass: write flat data
1671
+ assertFits( nodes.length, 'BLAS node count' );
1656
1672
  const data = new Float32Array( nodes.length * FLOATS_PER_NODE );
1657
1673
  const frontierMap = [];
1674
+ const idx = indexView( data );
1658
1675
 
1659
1676
  for ( let i = 0; i < nodes.length; i ++ ) {
1660
1677
 
@@ -1670,12 +1687,12 @@ export class BVHBuilder {
1670
1687
  data[ o ] = left.minX;
1671
1688
  data[ o + 1 ] = left.minY;
1672
1689
  data[ o + 2 ] = left.minZ;
1673
- data[ o + 3 ] = left._flatIndex;
1690
+ idx[ o + 3 ] = left._flatIndex;
1674
1691
 
1675
1692
  data[ o + 4 ] = left.maxX;
1676
1693
  data[ o + 5 ] = left.maxY;
1677
1694
  data[ o + 6 ] = left.maxZ;
1678
- data[ o + 7 ] = right._flatIndex;
1695
+ idx[ o + 7 ] = right._flatIndex;
1679
1696
 
1680
1697
  data[ o + 8 ] = right.minX;
1681
1698
  data[ o + 9 ] = right.minY;
@@ -1687,21 +1704,19 @@ export class BVHBuilder {
1687
1704
 
1688
1705
  } else if ( node.isFrontier ) {
1689
1706
 
1690
- // Frontier leaf: mark with -2 sentinel, use the taskId stored on the node
1691
1707
  const taskId = node.frontierTaskId;
1692
- data[ o ] = node.triangleOffset;
1693
- data[ o + 1 ] = node.triangleCount;
1694
- data[ o + 2 ] = taskId;
1695
- data[ o + 3 ] = - 2; // Frontier sentinel
1708
+ idx[ o ] = node.triangleOffset;
1709
+ idx[ o + 1 ] = node.triangleCount;
1710
+ idx[ o + 2 ] = taskId;
1711
+ idx[ o + 3 ] = FRONTIER_LEAF;
1696
1712
 
1697
1713
  frontierMap.push( { taskId, flatIndex: i } );
1698
1714
 
1699
1715
  } else {
1700
1716
 
1701
- // Regular leaf
1702
- data[ o ] = node.triangleOffset;
1703
- data[ o + 1 ] = node.triangleCount;
1704
- data[ o + 3 ] = - 1; // Leaf marker
1717
+ idx[ o ] = node.triangleOffset;
1718
+ idx[ o + 1 ] = node.triangleCount;
1719
+ idx[ o + 3 ] = TRIANGLE_LEAF;
1705
1720
 
1706
1721
  }
1707
1722
 
@@ -1735,7 +1750,9 @@ export class BVHBuilder {
1735
1750
  }
1736
1751
 
1737
1752
  // Allocate final array
1753
+ assertFits( totalNodes, 'assembled BLAS node count' );
1738
1754
  const finalData = new Float32Array( totalNodes * FLOATS_PER_NODE );
1755
+ const finalIdx = indexView( finalData );
1739
1756
 
1740
1757
  // Copy top-level data
1741
1758
  finalData.set( topFlatData );
@@ -1766,12 +1783,11 @@ export class BVHBuilder {
1766
1783
 
1767
1784
  const o = destOffset + j * FLOATS_PER_NODE;
1768
1785
 
1769
- // Check if inner node (not a leaf: leaf has -1 at o+3)
1770
- if ( finalData[ o + 3 ] !== - 1 ) {
1786
+ // Leaf tags sit above every valid index, so one unsigned compare separates them.
1787
+ if ( finalIdx[ o + 3 ] < TRIANGLE_LEAF ) {
1771
1788
 
1772
- // Adjust leftChildIndex and rightChildIndex
1773
- finalData[ o + 3 ] += globalOffset;
1774
- finalData[ o + 7 ] += globalOffset;
1789
+ finalIdx[ o + 3 ] += globalOffset;
1790
+ finalIdx[ o + 7 ] += globalOffset;
1775
1791
 
1776
1792
  }
1777
1793