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/Headless.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The supported way to render without a person watching. Defaults are the batch renderer's —
|
|
3
|
-
* strict,
|
|
3
|
+
* strict, deterministic — all reversible, none reversible by accident.
|
|
4
4
|
*
|
|
5
5
|
* @example
|
|
6
6
|
* const shot = await renderHeadless( { model: url, width: 1920, height: 1080, samples: 256 } );
|
|
@@ -20,11 +20,10 @@ import { PathTracerApp } from './PathTracerApp.js';
|
|
|
20
20
|
* @param {number} [options.samples=64] - samples to accumulate
|
|
21
21
|
* @param {'linear'|'srgb'} [options.colorSpace='srgb']
|
|
22
22
|
* @param {boolean} [options.strict=true]
|
|
23
|
-
* @param {string} [options.profile='physical'] - see RENDER_PROFILES
|
|
24
23
|
* @param {boolean} [options.deterministic=true]
|
|
25
24
|
* @param {boolean} [options.allowEarlyRetire=false] - needs `deterministic: false` to be reachable
|
|
26
25
|
* @param {boolean} [options.denoise=false] - one final OIDN pass, read back instead of the raw accumulation
|
|
27
|
-
* @param {Object} [options.settings] - applied
|
|
26
|
+
* @param {Object} [options.settings] - applied before the model loads and again after it
|
|
28
27
|
* @param {function(number): void} [options.onProgress] - running sample count
|
|
29
28
|
* @returns {Promise<{data: Float32Array|Uint8ClampedArray, width: number, height: number,
|
|
30
29
|
* colorSpace: string, source: string, samples: number, retiredBy: string, issues: Object[], adapter: Object,
|
|
@@ -95,7 +94,6 @@ export async function openHeadless( {
|
|
|
95
94
|
width = 1920,
|
|
96
95
|
height = 1080,
|
|
97
96
|
strict = true,
|
|
98
|
-
profile = 'physical',
|
|
99
97
|
deterministic = true,
|
|
100
98
|
settings = null,
|
|
101
99
|
storage = false,
|
|
@@ -103,7 +101,7 @@ export async function openHeadless( {
|
|
|
103
101
|
} = {} ) {
|
|
104
102
|
|
|
105
103
|
// Off unless asked for: cached state from an earlier run must not change what a batch renders.
|
|
106
|
-
const app = new PathTracerApp( canvas ?? null, { autoResize: false, strict,
|
|
104
|
+
const app = new PathTracerApp( canvas ?? null, { autoResize: false, strict, storage, hostMemoryGB } );
|
|
107
105
|
|
|
108
106
|
try {
|
|
109
107
|
|
|
@@ -114,7 +112,10 @@ export async function openHeadless( {
|
|
|
114
112
|
await app.init();
|
|
115
113
|
app.setCanvasSize( width, height );
|
|
116
114
|
|
|
115
|
+
// Before the load as well: some are read while a model loads (areaLightIntensityScale).
|
|
116
|
+
if ( settings ) app.settings.setMany( settings, { silent: true } );
|
|
117
117
|
if ( model ) await app.loadModel( model );
|
|
118
|
+
// Again after it, over anything the model's metadata set.
|
|
118
119
|
if ( settings ) app.settings.setMany( settings, { silent: true } );
|
|
119
120
|
|
|
120
121
|
// After the model: scene metadata can turn adaptive sampling back on.
|
package/src/PathTracerApp.js
CHANGED
|
@@ -7,8 +7,8 @@ import { NRD } from './Stages/NRD.js';
|
|
|
7
7
|
import { Variance } from './Stages/Variance.js';
|
|
8
8
|
import { BilateralFilter } from './Stages/BilateralFilter.js';
|
|
9
9
|
import { EdgeFilter } from './Stages/EdgeFilter.js';
|
|
10
|
-
import { AutoExposure } from './Stages/AutoExposure.js';
|
|
11
|
-
import {
|
|
10
|
+
import { AutoExposure, AUTO_EXPOSURE_DEFAULTS } from './Stages/AutoExposure.js';
|
|
11
|
+
import { PRODUCTION_RENDER_CONFIG, INTERACTIVE_RENDER_CONFIG, modePresetSettings } from './EngineDefaults.js';
|
|
12
12
|
import { createLogger } from './utils/Logger.js';
|
|
13
13
|
import { EngineEvents } from './EngineEvents.js';
|
|
14
14
|
import { ISSUE_CODES } from './EngineIssues.js';
|
|
@@ -71,7 +71,9 @@ export class PathTracerApp extends RayzeeRenderer {
|
|
|
71
71
|
super( canvas, options );
|
|
72
72
|
this.setColorManagement( ColorManagement );
|
|
73
73
|
this.setStorageOpener( acquireSharedStorage );
|
|
74
|
+
// Per-axis render scale while the camera moves (0.5 = a quarter of the pixels); 1 turns it off.
|
|
74
75
|
this.settings.define( 'interactionRenderScale', {
|
|
76
|
+
default: 0.5,
|
|
75
77
|
apply: () => {
|
|
76
78
|
|
|
77
79
|
if ( this.stages?.pathTracer?.interactionMode ) this._requestRenderScale( this._interactionRenderScale() );
|
|
@@ -153,7 +155,7 @@ export class PathTracerApp extends RayzeeRenderer {
|
|
|
153
155
|
stages.variance = new Variance( renderer, { enabled: false } );
|
|
154
156
|
stages.bilateralFilter = new BilateralFilter( renderer, { enabled: false } );
|
|
155
157
|
stages.edgeFilter = new EdgeFilter( renderer, { enabled: false } );
|
|
156
|
-
stages.autoExposure = new AutoExposure( renderer, { enabled:
|
|
158
|
+
stages.autoExposure = new AutoExposure( renderer, { enabled: AUTO_EXPOSURE_DEFAULTS.autoExposure } );
|
|
157
159
|
|
|
158
160
|
return [
|
|
159
161
|
stages.normalDepth, stages.motionVector, stages.nrd, stages.asvgf,
|
|
@@ -17,7 +17,7 @@ import { diffuseTransmissionPlugin } from './GLTFDiffuseTransmission.js';
|
|
|
17
17
|
import { decodersOnDemand } from './GLTFDecoders.js';
|
|
18
18
|
import { extractSceneMetadata } from './SceneMetadata.js';
|
|
19
19
|
import { ISSUE_CODES } from '../EngineIssues.js';
|
|
20
|
-
import {
|
|
20
|
+
import { ENGINE_DEFAULTS } from '../EngineDefaults.js';
|
|
21
21
|
|
|
22
22
|
// Define supported file formats
|
|
23
23
|
// What the core reads itself; every other format is registered (registerFormat) or comes with an add-on.
|
|
@@ -70,7 +70,7 @@ function areaLightPowerFactor( node, width, height, userData ) {
|
|
|
70
70
|
*/
|
|
71
71
|
export class AssetLoader extends EventDispatcher {
|
|
72
72
|
|
|
73
|
-
constructor( scene, camera, controls, { issues = null,
|
|
73
|
+
constructor( scene, camera, controls, { issues = null, areaLightIntensityScale = null } = {} ) {
|
|
74
74
|
|
|
75
75
|
super();
|
|
76
76
|
this.scene = scene;
|
|
@@ -109,7 +109,7 @@ export class AssetLoader extends EventDispatcher {
|
|
|
109
109
|
this._formats = new Map();
|
|
110
110
|
|
|
111
111
|
this._issues = issues;
|
|
112
|
-
this.
|
|
112
|
+
this._areaLightIntensityScale = areaLightIntensityScale ?? ( () => ENGINE_DEFAULTS.areaLightIntensityScale );
|
|
113
113
|
|
|
114
114
|
// A glTF whose external texture 404s still loads. Only place the engine sees the URL.
|
|
115
115
|
// ZIP paths build their own managers and are not covered.
|
|
@@ -187,7 +187,8 @@ export class AssetLoader extends EventDispatcher {
|
|
|
187
187
|
|
|
188
188
|
_keyed( kind, id ) {
|
|
189
189
|
|
|
190
|
-
|
|
190
|
+
// The empty field held a profile name that was never set; kept so stored caches and sessions still match.
|
|
191
|
+
return id ? `${kind}::${id}` : null;
|
|
191
192
|
|
|
192
193
|
}
|
|
193
194
|
|
|
@@ -1175,7 +1176,7 @@ export class AssetLoader extends EventDispatcher {
|
|
|
1175
1176
|
const power = userData.intensity * areaLightPowerFactor( object, userData.width, userData.height, userData );
|
|
1176
1177
|
const light = new RectAreaLight(
|
|
1177
1178
|
new Color( ...userData.color ),
|
|
1178
|
-
power * this.
|
|
1179
|
+
power * this._areaLightIntensityScale(),
|
|
1179
1180
|
userData.width,
|
|
1180
1181
|
userData.height
|
|
1181
1182
|
);
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
import { ReinsertionOptimizer } from './ReinsertionOptimizer.js';
|
|
2
|
-
// Logger is worker-safe (globalThis only, storage access guarded)
|
|
2
|
+
// Logger is worker-safe (globalThis only, storage access guarded).
|
|
3
3
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
4
4
|
import { foldLeaves } from './BVHLeafFold.js';
|
|
5
5
|
import { hasWorkers } from '../Platform.js';
|
|
6
|
+
import { BVH_LEAF_MARKERS, bvhIndexView, assertBVHIndexFits, TRIANGLE_DATA_LAYOUT } from './BufferLayout.js';
|
|
6
7
|
|
|
7
8
|
const log = createLogger( 'bvh' );
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
// Index fields are u32 BIT PATTERNS, never float values: as floats they round past 2^24.
|
|
12
|
-
const TRIANGLE_LEAF = 0x40000000;
|
|
13
|
-
const FRONTIER_LEAF = 0x40000002;
|
|
14
|
-
const indexView = f32 => new Uint32Array( f32.buffer, f32.byteOffset, f32.length );
|
|
15
|
-
const BVH_MAX_INDEX = 0x40000000;
|
|
16
|
-
|
|
17
|
-
function assertFits( count, what ) {
|
|
18
|
-
|
|
19
|
-
if ( count >= BVH_MAX_INDEX ) throw new RangeError( `${what} is ${count}, at or past the BVH index limit of ${BVH_MAX_INDEX}` );
|
|
20
|
-
return count;
|
|
21
|
-
|
|
22
|
-
}
|
|
10
|
+
const TRIANGLE_LEAF = BVH_LEAF_MARKERS.TRIANGLE_LEAF;
|
|
11
|
+
const FRONTIER_LEAF = BVH_LEAF_MARKERS.FRONTIER;
|
|
23
12
|
|
|
24
13
|
// Injected, not imported: this module also runs inside the worker, and `?worker&inline`
|
|
25
14
|
// would embed a second copy of BVHWorker's source there.
|
|
@@ -31,16 +20,6 @@ export function setBVHWorkerFactory( factory ) {
|
|
|
31
20
|
|
|
32
21
|
}
|
|
33
22
|
|
|
34
|
-
// Inline copy of TRIANGLE_DATA_LAYOUT (mirrors Constants.js).
|
|
35
|
-
// Cannot import Constants.js because BVHBuilder runs inside BVHWorker
|
|
36
|
-
// where `window` (used elsewhere in Constants.js) is not defined.
|
|
37
|
-
const TRIANGLE_DATA_LAYOUT = {
|
|
38
|
-
FLOATS_PER_TRIANGLE: 20,
|
|
39
|
-
POSITION_A_OFFSET: 0,
|
|
40
|
-
POSITION_B_OFFSET: 4,
|
|
41
|
-
POSITION_C_OFFSET: 8
|
|
42
|
-
};
|
|
43
|
-
|
|
44
23
|
const FPT = TRIANGLE_DATA_LAYOUT.FLOATS_PER_TRIANGLE;
|
|
45
24
|
|
|
46
25
|
// The record buffer is uint; positions are f32 in it. Views share the memory, no copy.
|
|
@@ -1507,9 +1486,9 @@ export class BVHBuilder {
|
|
|
1507
1486
|
// Inner: [leftMin.xyz, leftChild] [leftMax.xyz, rightChild] [rightMin.xyz, 0] [rightMax.xyz, 0]
|
|
1508
1487
|
// Leaf: [triOffset, triCount, 0, -1] [0,0,0,0] [0,0,0,0] [0,0,0,0]
|
|
1509
1488
|
const FLOATS_PER_NODE = 16;
|
|
1510
|
-
|
|
1489
|
+
assertBVHIndexFits( nodes.length, 'BLAS node count' );
|
|
1511
1490
|
const data = new Float32Array( nodes.length * FLOATS_PER_NODE );
|
|
1512
|
-
const idx =
|
|
1491
|
+
const idx = bvhIndexView( data );
|
|
1513
1492
|
|
|
1514
1493
|
for ( let i = 0; i < nodes.length; i ++ ) {
|
|
1515
1494
|
|
|
@@ -1581,10 +1560,10 @@ export class BVHBuilder {
|
|
|
1581
1560
|
}
|
|
1582
1561
|
|
|
1583
1562
|
// Second pass: write flat data
|
|
1584
|
-
|
|
1563
|
+
assertBVHIndexFits( nodes.length, 'BLAS node count' );
|
|
1585
1564
|
const data = new Float32Array( nodes.length * FLOATS_PER_NODE );
|
|
1586
1565
|
const frontierMap = [];
|
|
1587
|
-
const idx =
|
|
1566
|
+
const idx = bvhIndexView( data );
|
|
1588
1567
|
|
|
1589
1568
|
for ( let i = 0; i < nodes.length; i ++ ) {
|
|
1590
1569
|
|
|
@@ -1663,9 +1642,9 @@ export class BVHBuilder {
|
|
|
1663
1642
|
}
|
|
1664
1643
|
|
|
1665
1644
|
// Allocate final array
|
|
1666
|
-
|
|
1645
|
+
assertBVHIndexFits( totalNodes, 'assembled BLAS node count' );
|
|
1667
1646
|
const finalData = new Float32Array( totalNodes * FLOATS_PER_NODE );
|
|
1668
|
-
const finalIdx =
|
|
1647
|
+
const finalIdx = bvhIndexView( finalData );
|
|
1669
1648
|
|
|
1670
1649
|
// Copy top-level data
|
|
1671
1650
|
finalData.set( topFlatData );
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const TRIANGLE_LEAF =
|
|
4
|
-
const BVH_MAX_INDEX = 0x40000000;
|
|
5
|
-
const BVH_FOLDED_LEAF_MAX = 15;
|
|
1
|
+
import { BVH_LEAF_MARKERS, BVH_MAX_INDEX, BVH_FOLDED_LEAF_MAX } from './BufferLayout.js';
|
|
2
|
+
|
|
3
|
+
const TRIANGLE_LEAF = BVH_LEAF_MARKERS.TRIANGLE_LEAF;
|
|
6
4
|
const FLOATS_PER_NODE = 16;
|
|
7
5
|
const FOLDED = 0x80000000;
|
|
8
6
|
|
|
9
|
-
/** A folded leaf as its parent stores it (
|
|
7
|
+
/** A folded leaf as its parent stores it (see BVH_FOLDED_LEAF_MAX). */
|
|
10
8
|
export const foldedRef = ( first, count ) => ( ~ ( ( first << 4 ) | count ) ) >>> 0;
|
|
11
9
|
export const isFoldedRef = ref => ref >= FOLDED;
|
|
12
10
|
export const foldedFirst = ref => ( ( ~ ref ) >>> 0 ) >>> 4;
|
|
@@ -10,18 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { isFoldedRef, foldedFirst, foldedCount } from './BVHLeafFold.js';
|
|
13
|
-
|
|
14
|
-
// Inline copy of layout constants (source of truth: EngineDefaults.js).
|
|
15
|
-
// Cannot import because this runs inside Web Workers where window is not defined.
|
|
16
|
-
const TRIANGLE_DATA_LAYOUT = {
|
|
17
|
-
FLOATS_PER_TRIANGLE: 20,
|
|
18
|
-
POSITION_A_OFFSET: 0,
|
|
19
|
-
POSITION_B_OFFSET: 4,
|
|
20
|
-
POSITION_C_OFFSET: 8,
|
|
21
|
-
NORMAL_A_PACKED_OFFSET: 3,
|
|
22
|
-
NORMAL_B_PACKED_OFFSET: 7,
|
|
23
|
-
NORMAL_C_PACKED_OFFSET: 11,
|
|
24
|
-
};
|
|
13
|
+
import { TRIANGLE_DATA_LAYOUT, packNormalOct, BVH_LEAF_MARKERS } from './BufferLayout.js';
|
|
25
14
|
|
|
26
15
|
const FPT = TRIANGLE_DATA_LAYOUT.FLOATS_PER_TRIANGLE;
|
|
27
16
|
|
|
@@ -62,41 +51,9 @@ const triAccess = ( triangleData ) => {
|
|
|
62
51
|
|
|
63
52
|
};
|
|
64
53
|
|
|
65
|
-
// Octahedral snorm16 pair, matching packNormalOct in EngineDefaults (not importable here).
|
|
66
|
-
function packNormalOct( x, y, z ) {
|
|
67
|
-
|
|
68
|
-
const len = Math.sqrt( x * x + y * y + z * z );
|
|
69
|
-
if ( len > 0 ) {
|
|
70
|
-
|
|
71
|
-
x /= len; y /= len; z /= len;
|
|
72
|
-
|
|
73
|
-
} else {
|
|
74
|
-
|
|
75
|
-
x = 0; y = 0; z = 1;
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const sum = Math.abs( x ) + Math.abs( y ) + Math.abs( z );
|
|
80
|
-
let u = x / sum, v = y / sum;
|
|
81
|
-
if ( z < 0 ) {
|
|
82
|
-
|
|
83
|
-
const au = u, av = v;
|
|
84
|
-
u = ( 1 - Math.abs( av ) ) * ( au >= 0 ? 1 : - 1 );
|
|
85
|
-
v = ( 1 - Math.abs( au ) ) * ( av >= 0 ? 1 : - 1 );
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const qu = Math.round( Math.min( 1, Math.max( - 1, u ) ) * 32767 ) & 0xffff;
|
|
90
|
-
const qv = Math.round( Math.min( 1, Math.max( - 1, v ) ) * 32767 ) & 0xffff;
|
|
91
|
-
return ( ( qv << 16 ) | qu ) >>> 0;
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
54
|
const FLOATS_PER_NODE = 16; // 4 vec4s per BVH node
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
const LEAF_MARKER = 0x40000000;
|
|
99
|
-
const BLAS_POINTER_MARKER = 0x40000001;
|
|
55
|
+
const LEAF_MARKER = BVH_LEAF_MARKERS.TRIANGLE_LEAF;
|
|
56
|
+
const BLAS_POINTER_MARKER = BVH_LEAF_MARKERS.BLAS_POINTER_LEAF;
|
|
100
57
|
|
|
101
58
|
// Relative to the matrix's own magnitude, never an absolute floor — see transformBoundsToWorld.
|
|
102
59
|
const SINGULAR_REL_EPS = 1e-12;
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Triangle record: 5 uvec4 lanes (80 bytes). The buffer is declared `uvec4` so packed lanes
|
|
3
|
+
* keep their exact bit pattern — a packSnorm2x16 result can land in the f32 NaN range, and an
|
|
4
|
+
* f32 lane may canonicalise it (the same reason the G-buffer is uvec4). Positions and UVs are
|
|
5
|
+
* written as f32 through a Float32Array view of the same memory and read back with
|
|
6
|
+
* `uintBitsToFloat`, so they carry full precision; only normals are compressed.
|
|
7
|
+
*
|
|
8
|
+
* Was 32 floats (128 B) with 4 dead padding lanes. At 128 B the 2 GB V8 ArrayBuffer cap put a
|
|
9
|
+
* hard ceiling of 16.7M triangles on the scene — 80 B lifts that to 26.8M and cuts geometry
|
|
10
|
+
* VRAM by the same 37.5%. Each normal now rides in its position's spare .w lane, so the three
|
|
11
|
+
* vec4 loads the intersection test already does carry the normals with them.
|
|
12
|
+
*/
|
|
13
|
+
export const TRIANGLE_DATA_LAYOUT = {
|
|
14
|
+
FLOATS_PER_TRIANGLE: 20,
|
|
15
|
+
|
|
16
|
+
POSITION_A_OFFSET: 0, // f32 xyz + packed normal A
|
|
17
|
+
POSITION_B_OFFSET: 4,
|
|
18
|
+
POSITION_C_OFFSET: 8,
|
|
19
|
+
|
|
20
|
+
NORMAL_A_PACKED_OFFSET: 3, // oct16 in each position's .w lane
|
|
21
|
+
NORMAL_B_PACKED_OFFSET: 7,
|
|
22
|
+
NORMAL_C_PACKED_OFFSET: 11,
|
|
23
|
+
|
|
24
|
+
UV_AB_OFFSET: 12, // f32 uvA.xy, uvB.xy
|
|
25
|
+
UV_C_OFFSET: 16, // f32 uvC.xy
|
|
26
|
+
MATERIAL_FLAGS_OFFSET: 18, // materialIndex | side << 24 | shadowBlockerBits << 26 (two bits)
|
|
27
|
+
MESH_INDEX_OFFSET: 19
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const TRI_MATERIAL_MASK = 0xffffff;
|
|
31
|
+
export const TRI_SIDE_SHIFT = 24; // 0 front, 1 back, 2 double
|
|
32
|
+
export const TRI_BLOCKER_SHIFT = 26; // 1 = blocks shadow rays whatever the settings
|
|
33
|
+
export const TRI_BLOCKER_ALPHA_SHIFT = 27; // 1 = blocks them unless alpha-cutout shadows are on
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* How a shadow ray settles on this material without fetching it, mirroring traceShadowRay:
|
|
37
|
+
* bit 0 set = always a blocker; bit 1 set = a blocker while alpha-cutout shadows are off
|
|
38
|
+
* (MASK/BLEND with nothing else letting light through); 0 = light may pass, so the shadow
|
|
39
|
+
* traversal has to find the nearest such surface.
|
|
40
|
+
*/
|
|
41
|
+
export function shadowBlockerBits( material ) {
|
|
42
|
+
|
|
43
|
+
if ( ! material ) return 0;
|
|
44
|
+
const solid = ( material.transmission || 0 ) === 0
|
|
45
|
+
&& ( ( material.transparent | 0 ) === 0 || ( material.opacity ?? 1 ) >= 1 );
|
|
46
|
+
if ( ! solid ) return 0;
|
|
47
|
+
return ( material.alphaMode | 0 ) === 0 ? 1 : 2;
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Material index plus the per-triangle flags the shader reads without touching the
|
|
53
|
+
* material buffer: `side` for inline culling and the two shadow-blocker bits.
|
|
54
|
+
*/
|
|
55
|
+
export function packTriangleFlags( materialIndex, material ) {
|
|
56
|
+
|
|
57
|
+
return ( ( materialIndex & TRI_MATERIAL_MASK )
|
|
58
|
+
| ( ( material?.side ?? 0 ) << TRI_SIDE_SHIFT )
|
|
59
|
+
| ( shadowBlockerBits( material ) << TRI_BLOCKER_SHIFT ) ) >>> 0;
|
|
60
|
+
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Octahedral-encode a unit normal into one u32 (two snorm16). Worst-case error is ~0.03°,
|
|
65
|
+
* well under what normal maps and barycentric interpolation already contribute.
|
|
66
|
+
* A degenerate (zero-length) normal encodes as +Z rather than NaN.
|
|
67
|
+
*/
|
|
68
|
+
export function packNormalOct( x, y, z ) {
|
|
69
|
+
|
|
70
|
+
const len = Math.sqrt( x * x + y * y + z * z );
|
|
71
|
+
if ( len > 0 ) {
|
|
72
|
+
|
|
73
|
+
x /= len; y /= len; z /= len;
|
|
74
|
+
|
|
75
|
+
} else {
|
|
76
|
+
|
|
77
|
+
x = 0; y = 0; z = 1;
|
|
78
|
+
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const sum = Math.abs( x ) + Math.abs( y ) + Math.abs( z );
|
|
82
|
+
let u = x / sum, v = y / sum;
|
|
83
|
+
if ( z < 0 ) {
|
|
84
|
+
|
|
85
|
+
const au = u, av = v;
|
|
86
|
+
u = ( 1 - Math.abs( av ) ) * ( au >= 0 ? 1 : - 1 );
|
|
87
|
+
v = ( 1 - Math.abs( au ) ) * ( av >= 0 ? 1 : - 1 );
|
|
88
|
+
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const qu = Math.round( Math.min( 1, Math.max( - 1, u ) ) * 32767 ) & 0xffff;
|
|
92
|
+
const qv = Math.round( Math.min( 1, Math.max( - 1, v ) ) * 32767 ) & 0xffff;
|
|
93
|
+
return ( ( qv << 16 ) | qu ) >>> 0;
|
|
94
|
+
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Inverse of packNormalOct; writes into `out` (length >= 3) and returns it. */
|
|
98
|
+
export function unpackNormalOct( packed, out ) {
|
|
99
|
+
|
|
100
|
+
const u = ( ( packed << 16 ) >> 16 ) / 32767;
|
|
101
|
+
const v = ( packed >> 16 ) / 32767;
|
|
102
|
+
let x = u, y = v, z = 1 - Math.abs( u ) - Math.abs( v );
|
|
103
|
+
if ( z < 0 ) {
|
|
104
|
+
|
|
105
|
+
const ax = x, ay = y;
|
|
106
|
+
x = ( 1 - Math.abs( ay ) ) * ( ax >= 0 ? 1 : - 1 );
|
|
107
|
+
y = ( 1 - Math.abs( ax ) ) * ( ay >= 0 ? 1 : - 1 );
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const len = Math.sqrt( x * x + y * y + z * z ) || 1;
|
|
112
|
+
out[ 0 ] = x / len; out[ 1 ] = y / len; out[ 2 ] = z / len;
|
|
113
|
+
return out;
|
|
114
|
+
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Material data layout constants — single source of truth for material buffer offsets.
|
|
118
|
+
// Shared between CPU writers (TextureCreator, MaterialDataManager) and GPU readers (Common.js getMaterial).
|
|
119
|
+
export const MATERIAL_DATA_LAYOUT = {
|
|
120
|
+
|
|
121
|
+
SLOTS_PER_MATERIAL: 34, // vec4 slots per material
|
|
122
|
+
FLOATS_PER_MATERIAL: 136, // total floats per material (34 × 4)
|
|
123
|
+
|
|
124
|
+
// ── Flat float offsets (CPU side) ────────────────────────────────
|
|
125
|
+
// Used as: data[ materialIndex * FLOATS_PER_MATERIAL + offset ]
|
|
126
|
+
// Ordered for cache-line coherence: shadow/culling → BxDF core → maps → extended → transforms
|
|
127
|
+
|
|
128
|
+
// Slot 0: ior + transmission + thickness + emissiveIntensity [shadow]
|
|
129
|
+
IOR: 0, TRANSMISSION: 1, THICKNESS: 2, EMISSIVE_INTENSITY: 3,
|
|
130
|
+
// Slot 1: attenuationColor.rgb + attenuationDistance [shadow]
|
|
131
|
+
ATTENUATION_COLOR: 4, ATTENUATION_DISTANCE: 7,
|
|
132
|
+
// Slot 2: opacity + side + transparent + alphaTest [shadow + culling]
|
|
133
|
+
OPACITY: 8, SIDE: 9, TRANSPARENT: 10, ALPHA_TEST: 11,
|
|
134
|
+
// Slot 3: alphaMode + depthWrite + normalScale [shadow]
|
|
135
|
+
ALPHA_MODE: 12, DEPTH_WRITE: 13, NORMAL_SCALE: 14,
|
|
136
|
+
// Slot 4: color.rgb + metalness [BxDF core]
|
|
137
|
+
COLOR: 16, METALNESS: 19,
|
|
138
|
+
// Slot 5: emissive.rgb + roughness [BxDF core]
|
|
139
|
+
EMISSIVE: 20, ROUGHNESS: 23,
|
|
140
|
+
// Slot 6: map indices (albedo, normal, roughness, metalness) [maps]
|
|
141
|
+
ALBEDO_MAP_INDEX: 24, NORMAL_MAP_INDEX: 25, ROUGHNESS_MAP_INDEX: 26, METALNESS_MAP_INDEX: 27,
|
|
142
|
+
// Slot 7: map indices (emissive, bump) + clearcoat [maps]
|
|
143
|
+
EMISSIVE_MAP_INDEX: 28, BUMP_MAP_INDEX: 29, CLEARCOAT: 30, CLEARCOAT_ROUGHNESS: 31,
|
|
144
|
+
// Slot 8: dispersion + visible + sheen + sheenRoughness [extended BxDF]
|
|
145
|
+
DISPERSION: 32, VISIBLE: 33, SHEEN: 34, SHEEN_ROUGHNESS: 35,
|
|
146
|
+
// Slot 9: sheenColor.rgb + diffuseTransmission [extended BxDF]
|
|
147
|
+
SHEEN_COLOR: 36, DIFFUSE_TRANSMISSION: 39,
|
|
148
|
+
// Slot 10: specularIntensity + specularColor.rgb [extended BxDF]
|
|
149
|
+
SPECULAR_INTENSITY: 40, SPECULAR_COLOR: 41,
|
|
150
|
+
// Slot 11: iridescence + iridescenceIOR + iridescenceThicknessRange [extended BxDF]
|
|
151
|
+
IRIDESCENCE: 44, IRIDESCENCE_IOR: 45, IRIDESCENCE_THICKNESS_RANGE: 46,
|
|
152
|
+
// Slot 12: bumpScale + displacementScale + displacementMapIndex + (padding)
|
|
153
|
+
BUMP_SCALE: 48, DISPLACEMENT_SCALE: 49, DISPLACEMENT_MAP_INDEX: 50,
|
|
154
|
+
|
|
155
|
+
// ── Transform float offsets (8 floats each: 7 matrix values + 1 padding) ──
|
|
156
|
+
ALBEDO_TRANSFORM: 52,
|
|
157
|
+
NORMAL_TRANSFORM: 60,
|
|
158
|
+
ROUGHNESS_TRANSFORM: 68,
|
|
159
|
+
METALNESS_TRANSFORM: 76,
|
|
160
|
+
EMISSIVE_TRANSFORM: 84,
|
|
161
|
+
BUMP_TRANSFORM: 92,
|
|
162
|
+
DISPLACEMENT_TRANSFORM: 100,
|
|
163
|
+
|
|
164
|
+
// ── Subsurface scattering (3 slots appended after transforms) ────
|
|
165
|
+
// Slot 27: subsurfaceColor.rgb (scatter albedo) + subsurface weight
|
|
166
|
+
SUBSURFACE_COLOR: 108, SUBSURFACE: 111,
|
|
167
|
+
// Slot 28: subsurfaceRadius.rgb (mean free path) + radius scale
|
|
168
|
+
SUBSURFACE_RADIUS: 112, SUBSURFACE_RADIUS_SCALE: 115,
|
|
169
|
+
// Slot 29: subsurfaceAnisotropy g (116) + surface anisotropy (strength 117, rotation 118, map index 119)
|
|
170
|
+
SUBSURFACE_ANISOTROPY: 116, ANISOTROPY: 117, ANISOTROPY_ROTATION: 118, ANISOTROPY_MAP_INDEX: 119,
|
|
171
|
+
// Slot 30: extension-texture map indices A (transmission, clearcoat, clearcoatRoughness, sheenColor)
|
|
172
|
+
TRANSMISSION_MAP_INDEX: 120, CLEARCOAT_MAP_INDEX: 121, CLEARCOAT_ROUGHNESS_MAP_INDEX: 122, SHEEN_COLOR_MAP_INDEX: 123,
|
|
173
|
+
// Slot 31: extension-texture map indices B (sheenRoughness, iridescence, iridescenceThickness, specularIntensity)
|
|
174
|
+
SHEEN_ROUGHNESS_MAP_INDEX: 124, IRIDESCENCE_MAP_INDEX: 125, IRIDESCENCE_THICKNESS_MAP_INDEX: 126, SPECULAR_INTENSITY_MAP_INDEX: 127,
|
|
175
|
+
// Slot 32: extension-texture map index C (specularColor) + diffuseTransmissionColor.rgb
|
|
176
|
+
SPECULAR_COLOR_MAP_INDEX: 128, DIFFUSE_TRANSMISSION_COLOR: 129,
|
|
177
|
+
// Slot 33: extension-texture map indices D (diffuseTransmission, diffuseTransmissionColor) + 2 reserved;
|
|
178
|
+
// read only for a material with diffuse transmission
|
|
179
|
+
DIFFUSE_TRANSMISSION_MAP_INDEX: 132, DIFFUSE_TRANSMISSION_COLOR_MAP_INDEX: 133,
|
|
180
|
+
|
|
181
|
+
// ── Vec4 slot indices (GPU/TSL side) ─────────────────────────────
|
|
182
|
+
// Used with getDatafromStorageBuffer( buf, matIdx, int(slot), int(SLOTS_PER_MATERIAL) )
|
|
183
|
+
SLOT: {
|
|
184
|
+
IOR_TRANSMISSION: 0, // [shadow] ior, transmission, thickness, emissiveIntensity
|
|
185
|
+
ATTENUATION: 1, // [shadow] attenuationColor, attenuationDistance
|
|
186
|
+
OPACITY_ALPHA: 2, // [shadow+culling] opacity, side, transparent, alphaTest
|
|
187
|
+
ALPHA_MODE: 3, // [shadow] alphaMode, depthWrite, normalScale
|
|
188
|
+
COLOR_METALNESS: 4, // [BxDF] color.rgb, metalness
|
|
189
|
+
EMISSIVE_ROUGHNESS: 5, // [BxDF] emissive.rgb, roughness
|
|
190
|
+
MAP_INDICES_A: 6, // [maps] albedo, normal, roughness, metalness
|
|
191
|
+
MAP_INDICES_B: 7, // [maps] emissive, bump, clearcoat, clearcoatRoughness
|
|
192
|
+
DISPERSION_SHEEN: 8, // [extended] dispersion, visible, sheen, sheenRoughness
|
|
193
|
+
SHEEN_COLOR: 9, // [extended] sheenColor, diffuseTransmission
|
|
194
|
+
SPECULAR: 10, // [extended] specularIntensity, specularColor
|
|
195
|
+
IRIDESCENCE: 11, // [extended] iridescence, iridescenceIOR, iridescenceThicknessRange
|
|
196
|
+
BUMP_DISPLACEMENT: 12, // bumpScale, displacementScale, displacementMapIndex
|
|
197
|
+
ALBEDO_TRANSFORM_A: 13, ALBEDO_TRANSFORM_B: 14,
|
|
198
|
+
NORMAL_TRANSFORM_A: 15, NORMAL_TRANSFORM_B: 16,
|
|
199
|
+
ROUGHNESS_TRANSFORM_A: 17, ROUGHNESS_TRANSFORM_B: 18,
|
|
200
|
+
METALNESS_TRANSFORM_A: 19, METALNESS_TRANSFORM_B: 20,
|
|
201
|
+
EMISSIVE_TRANSFORM_A: 21, EMISSIVE_TRANSFORM_B: 22,
|
|
202
|
+
BUMP_TRANSFORM_A: 23, BUMP_TRANSFORM_B: 24,
|
|
203
|
+
DISPLACEMENT_TRANSFORM_A: 25, DISPLACEMENT_TRANSFORM_B: 26,
|
|
204
|
+
SUBSURFACE_A: 27, // subsurfaceColor.rgb, subsurface weight
|
|
205
|
+
SUBSURFACE_B: 28, // subsurfaceRadius.rgb, subsurfaceRadiusScale
|
|
206
|
+
SUBSURFACE_C: 29, // subsurfaceAnisotropy g, anisotropy, anisotropyRotation, anisotropyMapIndex
|
|
207
|
+
EXT_MAP_INDICES_A: 30, // transmission, clearcoat, clearcoatRoughness, sheenColor map indices
|
|
208
|
+
EXT_MAP_INDICES_B: 31, // sheenRoughness, iridescence, iridescenceThickness, specularIntensity map indices
|
|
209
|
+
EXT_MAP_INDICES_C: 32, // specularColor map index, diffuseTransmissionColor
|
|
210
|
+
EXT_MAP_INDICES_D: 33, // diffuseTransmission, diffuseTransmissionColor map indices + 2 reserved
|
|
211
|
+
},
|
|
212
|
+
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// glTF/three.js spell "no volume absorption" as attenuationDistance = Infinity, while the GPU
|
|
216
|
+
// contract is `> 0 = on` (calculateBeerLawAbsorption). Every writer into ATTENUATION_DISTANCE
|
|
217
|
+
// collapses both spellings to 0 so no shader divides by Inf.
|
|
218
|
+
export const normalizeAttenuationDistance = d => ( Number.isFinite( d ) && d > 0 ? d : 0 );
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Node tags, written into slot [3] of a BVH node as a raw u32 bit pattern.
|
|
222
|
+
*
|
|
223
|
+
* Node indices, triangle offsets and counts are integers living inside a Float32Array. Written as
|
|
224
|
+
* float *values* they round silently past 2^24 (16,777,216): in a 24M-node scene half of every
|
|
225
|
+
* BLAS pointer landed on a neighbouring node and that geometry vanished from the render with no
|
|
226
|
+
* error at all. Every one of those fields is written as a u32 bit pattern instead, exact to 2^30.
|
|
227
|
+
*
|
|
228
|
+
* Tags sit above {@link BVH_MAX_INDEX} so a single unsigned compare separates a leaf from an inner
|
|
229
|
+
* node's left-child index. All three are ordinary finite floats — nothing lands in the NaN range,
|
|
230
|
+
* which an f32 storage buffer is free to canonicalise.
|
|
231
|
+
*/
|
|
232
|
+
export const BVH_MAX_INDEX = 0x40000000; // 2^30
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Slot [1] of a BLAS-pointer leaf holds its placement index, which {@link BVH_MAX_INDEX} keeps
|
|
236
|
+
* below 2^30. Bit 30 is therefore free to say the leaf's matrix is identity: geometry no other
|
|
237
|
+
* placement shares is baked to world space at extraction, and a ray reaching it needs no
|
|
238
|
+
* transform at all. Mask the bit off before using the slot as an index.
|
|
239
|
+
*/
|
|
240
|
+
export const TLAS_LEAF_IDENTITY = 0x40000000;
|
|
241
|
+
export const TLAS_PLACEMENT_MASK = 0x3fffffff;
|
|
242
|
+
|
|
243
|
+
export const BVH_LEAF_MARKERS = {
|
|
244
|
+
TRIANGLE_LEAF: 0x40000000, // leaf containing triangle references
|
|
245
|
+
BLAS_POINTER_LEAF: 0x40000001, // TLAS leaf pointing to a BLAS root node
|
|
246
|
+
FRONTIER: 0x40000002, // parallel-build placeholder, overwritten during assembly
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* A triangle leaf of at most this many triangles is folded into its parent: the child's slot ([3]
|
|
251
|
+
* or [7]) holds `~( first << 4 | count )`, the very value traversal pushes, so an inner node is
|
|
252
|
+
* read exactly as before and only popping a negative entry differs. Node indices stay below
|
|
253
|
+
* {@link BVH_MAX_INDEX}, leaf tags between it and 2^31, folded leaves from 2^31 up — so the count
|
|
254
|
+
* has four bits and the first triangle must stay below {@link BVH_FOLDED_FIRST_LIMIT}.
|
|
255
|
+
*/
|
|
256
|
+
export const BVH_FOLDED_LEAF_MAX = 15;
|
|
257
|
+
export const BVH_FOLDED_FIRST_LIMIT = 1 << 27;
|
|
258
|
+
|
|
259
|
+
/** A u32 view over a float buffer, for writing index fields as exact bit patterns. */
|
|
260
|
+
export function bvhIndexView( f32 ) {
|
|
261
|
+
|
|
262
|
+
return new Uint32Array( f32.buffer, f32.byteOffset, f32.length );
|
|
263
|
+
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Refuse to build a BVH whose indices would collide with the leaf tags.
|
|
268
|
+
*
|
|
269
|
+
* Throws rather than degrades: the failure this replaces was a scene that rendered with half its
|
|
270
|
+
* geometry silently missing, which is far worse than a scene that refuses to load. Guarding the
|
|
271
|
+
* totals covers every individual write, since no index can exceed the count it indexes into.
|
|
272
|
+
*
|
|
273
|
+
* @param {number} count - node or triangle total about to be indexed
|
|
274
|
+
* @param {string} what - what the count is, for the message
|
|
275
|
+
* @throws {RangeError}
|
|
276
|
+
*/
|
|
277
|
+
export function assertBVHIndexFits( count, what ) {
|
|
278
|
+
|
|
279
|
+
if ( count >= BVH_MAX_INDEX ) {
|
|
280
|
+
|
|
281
|
+
throw new RangeError(
|
|
282
|
+
`${what} is ${count.toLocaleString()}, at or past the BVH index limit of ` +
|
|
283
|
+
`${BVH_MAX_INDEX.toLocaleString()}. Node indices are stored as u32 bit patterns and the ` +
|
|
284
|
+
'leaf tags occupy everything above that.'
|
|
285
|
+
);
|
|
286
|
+
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return count;
|
|
290
|
+
|
|
291
|
+
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { DataTexture, RGBAFormat, FloatType, NearestFilter } from 'three';
|
|
10
|
-
import { TRIANGLE_DATA_LAYOUT, TRI_MATERIAL_MASK } from '
|
|
10
|
+
import { TRIANGLE_DATA_LAYOUT, TRI_MATERIAL_MASK } from './BufferLayout.js';
|
|
11
11
|
import { LightBVHBuilder } from './LightBVHBuilder.js';
|
|
12
12
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
13
13
|
import { convertLinearTriple, getWorkingMatrix } from '../Color/WorkingMatrix.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BufferAttribute, Vector3, Vector2, Color, Matrix3, Matrix4, FrontSide, BackSide, DoubleSide, RGBAFormat } from "three";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
} from '
|
|
2
|
+
import { MATERIAL_DEFAULTS } from '../EngineDefaults.js';
|
|
3
|
+
import { TRIANGLE_DATA_LAYOUT, packNormalOct, packTriangleFlags } from './BufferLayout.js';
|
|
4
|
+
import { TEXTURE_CONSTANTS } from './TextureBuckets.js';
|
|
5
5
|
import { ISSUE_CODES } from '../EngineIssues.js';
|
|
6
6
|
import { ChunkedRecords, SHARED_MEMORY_AVAILABLE } from './ChunkedRecords.js';
|
|
7
7
|
import { createLogger, fmt, warnOnce } from '../utils/Logger.js';
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* that actually runs out (BVH assembly), where it asks only for that step's bytes.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { TRIANGLE_DATA_LAYOUT } from '
|
|
17
|
+
import { TRIANGLE_DATA_LAYOUT } from './BufferLayout.js';
|
|
18
18
|
import { DEFAULT_CHUNK_BYTES } from './ChunkedRecords.js';
|
|
19
19
|
|
|
20
20
|
/** Bytes one stored triangle occupies in the triangle records. */
|
|
@@ -59,6 +59,12 @@ export const SAFE_SCENE_BYTES = 7040 * 1024 * 1024;
|
|
|
59
59
|
*/
|
|
60
60
|
export const MAX_SCENE_BYTES = 9216 * 1024 * 1024;
|
|
61
61
|
|
|
62
|
+
// Scene-archive budgets with the memory spill on: the triangles and BVH leave the heap as the build goes, so the host
|
|
63
|
+
// passes these instead of the importer's own. The whole 15-part Moana subset (55.7M / 7.0M) loads cold under them, at
|
|
64
|
+
// an 8.1 GB preflight estimate; the preflight, not the budget, refuses anything larger.
|
|
65
|
+
export const SPILL_TRIANGLE_BUDGET = 60_000_000;
|
|
66
|
+
export const SPILL_PLACEMENT_BUDGET = 8_000_000;
|
|
67
|
+
|
|
62
68
|
/**
|
|
63
69
|
* The host's memory in GB: the host's own figure when it gives one, else Chrome's
|
|
64
70
|
* `navigator.deviceMemory`, else an assumed 4 (every other runtime lacks it).
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* denormalised one. World bounds and the inverse transform are derived on demand.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { TRIANGLE_DATA_LAYOUT, BVH_LEAF_MARKERS, assertBVHIndexFits, bvhIndexView } from './BufferLayout.js';
|
|
13
13
|
|
|
14
14
|
const IDENTITY = Float64Array.from( [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] );
|
|
15
15
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MATERIAL_DEFAULTS as D } from '../EngineDefaults.js';
|
|
2
|
+
import { MATERIAL_DATA_LAYOUT as M, normalizeAttenuationDistance } from './BufferLayout.js';
|
|
2
3
|
|
|
3
4
|
// The first 8 Matrix3 elements; the GPU rebuilds the 9th (always 1).
|
|
4
5
|
const IDENTITY_UV = [ 1, 0, 0, 0, 1, 0, 0, 0 ];
|
|
@@ -91,7 +91,7 @@ const DEFAULT_TRIANGLE_BUDGET = 45_000_000;
|
|
|
91
91
|
// Placements are their own budget: geometry is shared, but each costs a TLAS leaf and an
|
|
92
92
|
// instance record. isCoastline's 5.09M loaded and rendered at 23 fps.
|
|
93
93
|
const DEFAULT_PLACEMENT_BUDGET = 6_000_000;
|
|
94
|
-
export { SPILL_TRIANGLE_BUDGET, SPILL_PLACEMENT_BUDGET } from '
|
|
94
|
+
export { SPILL_TRIANGLE_BUDGET, SPILL_PLACEMENT_BUDGET } from '../HostMemory.js';
|
|
95
95
|
// Non-instanced shapes merge into a few large meshes: isPalmRig declares 173,338 of them,
|
|
96
96
|
// and one BufferGeometry + Mesh each measured 3.3 GB — the loader OOM'd before tracing.
|
|
97
97
|
const DEFAULT_MERGE_MIN_SHAPES = 256;
|