rayzee 8.5.0 → 8.6.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 +60 -4
- package/dist/{DLSSNeural-BNSJ8V3z.js → DLSSNeural-BhBCBgKf.js} +5 -5
- package/dist/{DLSSSuperRes-BoEW89Cl.js → DLSSSuperRes-BCA7F_k5.js} +5 -5
- package/dist/ToneMapGPU-BzcLheoR.js +533 -0
- package/dist/rayzee.es.js +27198 -9047
- package/dist/rayzee.umd.js +255 -187
- package/package.json +1 -1
- package/src/AssetConfig.js +15 -2
- package/src/Color/BakedViews.js +134 -0
- package/src/Color/BuiltinViews.js +261 -0
- package/src/Color/ColorManagement.js +1130 -0
- package/src/Color/ColorSpaces.js +432 -0
- package/src/Color/Displays.js +19 -0
- package/src/Color/InputColorSpaces.js +243 -0
- package/src/Color/LutBake.js +371 -0
- package/src/Color/OcioRuntime.js +338 -0
- package/src/Color/OcioViews.js +419 -0
- package/src/Color/ViewTransforms.js +323 -0
- package/src/Color/WorkingMatrix.js +86 -0
- package/src/EngineDefaults.js +55 -3
- package/src/EngineIssues.js +3 -0
- package/src/Passes/AIUpscaler.js +16 -7
- package/src/PathTracerApp.js +227 -7
- package/src/Processor/AssetLoader.js +1 -2
- package/src/Processor/EmissiveTriangleBuilder.js +34 -2
- package/src/Processor/GeometryExtractor.js +151 -138
- package/src/Processor/LightSerializer.js +8 -3
- package/src/Processor/MaterialPacking.js +168 -0
- package/src/Processor/PackedRayBuffer.js +6 -2
- package/src/Processor/ProceduralSky.js +4 -0
- package/src/Processor/SceneProcessor.js +25 -1
- package/src/Processor/SimpleSky.js +8 -0
- package/src/Processor/TextureCreator.js +137 -91
- package/src/Processor/TextureReadback.js +92 -0
- package/src/Processor/ToneMapCPU.js +80 -165
- package/src/Processor/ToneMapGPU.js +122 -151
- package/src/RenderSettings.js +1 -0
- package/src/Stages/Compositor.js +11 -2
- package/src/Stages/PathTracer.js +2 -0
- package/src/Stages/PathTracerStage.js +1 -1
- package/src/TSL/Common.js +15 -0
- package/src/TSL/Debugger.js +2 -3
- package/src/TSL/EmissiveSampling.js +6 -8
- package/src/TSL/ExtendKernel.js +9 -0
- package/src/TSL/Fresnel.js +23 -1
- package/src/TSL/HitFacet.js +102 -0
- package/src/TSL/LightsDirect.js +12 -33
- package/src/TSL/LightsSampling.js +15 -7
- package/src/TSL/MaterialEvaluation.js +26 -19
- package/src/TSL/MaterialProperties.js +74 -37
- package/src/TSL/MaterialTransmission.js +2 -3
- package/src/TSL/ShadeKernel.js +34 -21
- package/src/TSL/ShadowTerminator.js +125 -0
- package/src/TSL/Struct.js +9 -0
- package/src/TSL/Subsurface.js +2 -3
- package/src/index.js +29 -1
- package/src/managers/EnvironmentManager.js +20 -0
- package/src/managers/MaterialDataManager.js +118 -208
- package/src/managers/UniformManager.js +1 -0
- package/dist/ToneMapGPU-DzqSyzTx.js +0 -341
|
@@ -13,8 +13,14 @@ import {
|
|
|
13
13
|
MATERIAL_DATA_LAYOUT as M, TRIANGLE_DATA_LAYOUT as T, normalizeAttenuationDistance,
|
|
14
14
|
TRI_MATERIAL_MASK, TRI_SIDE_SHIFT, TRI_BLOCKER_SHIFT, shadowBlockerBits
|
|
15
15
|
} from '../EngineDefaults.js';
|
|
16
|
+
import { packMaterial, UNIT_RANGE_PROPERTIES, clampUnit } from '../Processor/MaterialPacking.js';
|
|
17
|
+
import { resolveMaterialTextures, MATERIAL_VALUE_SOURCE } from '../Processor/GeometryExtractor.js';
|
|
18
|
+
import { convertLinearTriple, convertLinearTriples, getWorkingMatrixSpace } from '../Color/WorkingMatrix.js';
|
|
16
19
|
import { createLogger, fmt } from '../utils/Logger.js';
|
|
17
20
|
|
|
21
|
+
/** Material buffers already moved into the working space, so a re-init cannot convert twice. */
|
|
22
|
+
const convertedBuffers = new WeakSet();
|
|
23
|
+
|
|
18
24
|
const log = createLogger( 'material' );
|
|
19
25
|
|
|
20
26
|
const PIXELS_PER_MATERIAL = M.SLOTS_PER_MATERIAL;
|
|
@@ -24,6 +30,15 @@ const TRI_FLAGS_OFFSET = T.MATERIAL_FLAGS_OFFSET;
|
|
|
24
30
|
// Material properties that affect the shadow-ray opaque-blocker flag.
|
|
25
31
|
const BLOCKER_PROPS = new Set( [ 'transmission', 'transparent', 'opacity', 'alphaMode' ] );
|
|
26
32
|
|
|
33
|
+
// Map slot → sRGB pool (true) or linear pool.
|
|
34
|
+
const TEXTURE_POOLS = [
|
|
35
|
+
[ 'map', true ], [ 'emissiveMap', true ], [ 'sheenColorMap', true ], [ 'specularColorMap', true ],
|
|
36
|
+
[ 'normalMap', false ], [ 'bumpMap', false ], [ 'roughnessMap', false ], [ 'metalnessMap', false ],
|
|
37
|
+
[ 'displacementMap', false ], [ 'anisotropyMap', false ], [ 'transmissionMap', false ],
|
|
38
|
+
[ 'clearcoatMap', false ], [ 'clearcoatRoughnessMap', false ], [ 'sheenRoughnessMap', false ],
|
|
39
|
+
[ 'iridescenceMap', false ], [ 'iridescenceThicknessMap', false ], [ 'specularIntensityMap', false ],
|
|
40
|
+
];
|
|
41
|
+
|
|
27
42
|
// Scalar slots readable via getMaterialProperty().
|
|
28
43
|
const SCALAR_PROPERTY_OFFSETS = {
|
|
29
44
|
ior: M.IOR,
|
|
@@ -83,18 +98,72 @@ export class MaterialDataManager {
|
|
|
83
98
|
*/
|
|
84
99
|
this.callbacks = {};
|
|
85
100
|
|
|
101
|
+
// Per material index: createMaterialObject's sources, and properties a host set since.
|
|
102
|
+
this._sources = [];
|
|
103
|
+
this._hostSet = [];
|
|
104
|
+
|
|
86
105
|
}
|
|
87
106
|
|
|
88
107
|
// ===== STORAGE BUFFER MANAGEMENT =====
|
|
89
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Every colour slot in the material buffer, in floats from the start of a material.
|
|
111
|
+
*
|
|
112
|
+
* Tints only — `attenuationColor` and `subsurfaceColor` included, because they multiply
|
|
113
|
+
* radiance like any other. Scalars and packed flags are deliberately absent: running a
|
|
114
|
+
* primaries matrix over roughness would be silent and ruinous.
|
|
115
|
+
*/
|
|
116
|
+
static COLOR_OFFSETS = [
|
|
117
|
+
M.COLOR, M.EMISSIVE, M.ATTENUATION_COLOR, M.SHEEN_COLOR, M.SPECULAR_COLOR, M.SUBSURFACE_COLOR,
|
|
118
|
+
].filter( o => Number.isInteger( o ) );
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Move every material tint into the working space.
|
|
122
|
+
*
|
|
123
|
+
* glTF authors colours against sRGB primaries. If the render is happening in ACEScg, the same
|
|
124
|
+
* numbers describe a different colour, so a base colour left unconverted is not a grade away
|
|
125
|
+
* from right — it is a different material. Inert until a working space is adopted.
|
|
126
|
+
*/
|
|
127
|
+
_convertColorsToWorkingSpace( data ) {
|
|
128
|
+
|
|
129
|
+
// The same array is handed in again whenever the stage re-initialises, and converting it
|
|
130
|
+
// twice would apply the primaries matrix twice — a colour shift with no error to show for
|
|
131
|
+
// it. Remembered by identity, so a rebuilt buffer converts normally.
|
|
132
|
+
if ( convertedBuffers.has( data ) ) return;
|
|
133
|
+
convertedBuffers.add( data );
|
|
134
|
+
|
|
135
|
+
const n = convertLinearTriples( data, M.FLOATS_PER_MATERIAL, MaterialDataManager.COLOR_OFFSETS );
|
|
136
|
+
if ( n ) log.debug( `converted ${n} material colour(s) into ${getWorkingMatrixSpace()}` );
|
|
137
|
+
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** One tint, converted on its way into the buffer. */
|
|
141
|
+
_writeColor( data, index, r, g, b ) {
|
|
142
|
+
|
|
143
|
+
const rgb = [ r, g, b ];
|
|
144
|
+
if ( convertLinearTriple( rgb ) ) {
|
|
145
|
+
|
|
146
|
+
[ r, g, b ] = rgb;
|
|
147
|
+
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
data[ index ] = r;
|
|
151
|
+
data[ index + 1 ] = g;
|
|
152
|
+
data[ index + 2 ] = b;
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|
|
90
156
|
/**
|
|
91
157
|
* Sets material data from raw Float32Array via storage buffer.
|
|
92
158
|
* @param {Float32Array} matImageData
|
|
159
|
+
* @param {Array<Object>} [sources] - createMaterialObject().sources per material index
|
|
93
160
|
*/
|
|
94
|
-
setMaterialData( matImageData ) {
|
|
161
|
+
setMaterialData( matImageData, sources = [] ) {
|
|
95
162
|
|
|
96
163
|
if ( ! matImageData ) return;
|
|
97
164
|
|
|
165
|
+
this._convertColorsToWorkingSpace( matImageData );
|
|
166
|
+
|
|
98
167
|
const vec4Count = matImageData.length / 4;
|
|
99
168
|
|
|
100
169
|
if ( this.materialStorageNode ) {
|
|
@@ -111,6 +180,8 @@ export class MaterialDataManager {
|
|
|
111
180
|
}
|
|
112
181
|
|
|
113
182
|
this.materialCount = Math.floor( vec4Count / PIXELS_PER_MATERIAL );
|
|
183
|
+
this._sources = [ ...sources ];
|
|
184
|
+
this._hostSet = [];
|
|
114
185
|
log.debug( `${fmt.n( this.materialCount )} materials (storage buffer)` );
|
|
115
186
|
|
|
116
187
|
}
|
|
@@ -225,6 +296,20 @@ export class MaterialDataManager {
|
|
|
225
296
|
|
|
226
297
|
}
|
|
227
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Where a material property's value came from, as a MATERIAL_VALUE_SOURCE. `default` means the
|
|
301
|
+
* model never said and the engine filled it in.
|
|
302
|
+
* @param {number} materialIndex
|
|
303
|
+
* @param {string} property
|
|
304
|
+
* @returns {string|undefined} undefined for an unknown property or material
|
|
305
|
+
*/
|
|
306
|
+
getMaterialPropertySource( materialIndex, property ) {
|
|
307
|
+
|
|
308
|
+
if ( this._hostSet[ materialIndex ]?.has( property ) ) return MATERIAL_VALUE_SOURCE.HOST;
|
|
309
|
+
return this._sources[ materialIndex ]?.[ property ];
|
|
310
|
+
|
|
311
|
+
}
|
|
312
|
+
|
|
228
313
|
/**
|
|
229
314
|
* Update a single material property in the storage buffer.
|
|
230
315
|
* @param {number} materialIndex
|
|
@@ -242,21 +327,18 @@ export class MaterialDataManager {
|
|
|
242
327
|
|
|
243
328
|
const data = this.materialStorageAttr.array;
|
|
244
329
|
const stride = materialIndex * M.FLOATS_PER_MATERIAL;
|
|
330
|
+
if ( UNIT_RANGE_PROPERTIES.has( property ) && typeof value === 'number' ) value = clampUnit( value );
|
|
245
331
|
|
|
246
332
|
switch ( property ) {
|
|
247
333
|
|
|
248
334
|
case 'color':
|
|
249
335
|
if ( value.r !== undefined ) {
|
|
250
336
|
|
|
251
|
-
data
|
|
252
|
-
data[ stride + M.COLOR + 1 ] = value.g;
|
|
253
|
-
data[ stride + M.COLOR + 2 ] = value.b;
|
|
337
|
+
this._writeColor( data, stride + M.COLOR, value.r, value.g, value.b );
|
|
254
338
|
|
|
255
339
|
} else if ( Array.isArray( value ) ) {
|
|
256
340
|
|
|
257
|
-
data
|
|
258
|
-
data[ stride + M.COLOR + 1 ] = value[ 1 ];
|
|
259
|
-
data[ stride + M.COLOR + 2 ] = value[ 2 ];
|
|
341
|
+
this._writeColor( data, stride + M.COLOR, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
260
342
|
|
|
261
343
|
}
|
|
262
344
|
|
|
@@ -265,15 +347,11 @@ export class MaterialDataManager {
|
|
|
265
347
|
case 'emissive':
|
|
266
348
|
if ( value.r !== undefined ) {
|
|
267
349
|
|
|
268
|
-
data
|
|
269
|
-
data[ stride + M.EMISSIVE + 1 ] = value.g;
|
|
270
|
-
data[ stride + M.EMISSIVE + 2 ] = value.b;
|
|
350
|
+
this._writeColor( data, stride + M.EMISSIVE, value.r, value.g, value.b );
|
|
271
351
|
|
|
272
352
|
} else if ( Array.isArray( value ) ) {
|
|
273
353
|
|
|
274
|
-
data
|
|
275
|
-
data[ stride + M.EMISSIVE + 1 ] = value[ 1 ];
|
|
276
|
-
data[ stride + M.EMISSIVE + 2 ] = value[ 2 ];
|
|
354
|
+
this._writeColor( data, stride + M.EMISSIVE, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
277
355
|
|
|
278
356
|
}
|
|
279
357
|
|
|
@@ -286,15 +364,11 @@ export class MaterialDataManager {
|
|
|
286
364
|
case 'attenuationColor':
|
|
287
365
|
if ( value.r !== undefined ) {
|
|
288
366
|
|
|
289
|
-
data
|
|
290
|
-
data[ stride + M.ATTENUATION_COLOR + 1 ] = value.g;
|
|
291
|
-
data[ stride + M.ATTENUATION_COLOR + 2 ] = value.b;
|
|
367
|
+
this._writeColor( data, stride + M.ATTENUATION_COLOR, value.r, value.g, value.b );
|
|
292
368
|
|
|
293
369
|
} else if ( Array.isArray( value ) ) {
|
|
294
370
|
|
|
295
|
-
data
|
|
296
|
-
data[ stride + M.ATTENUATION_COLOR + 1 ] = value[ 1 ];
|
|
297
|
-
data[ stride + M.ATTENUATION_COLOR + 2 ] = value[ 2 ];
|
|
371
|
+
this._writeColor( data, stride + M.ATTENUATION_COLOR, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
298
372
|
|
|
299
373
|
}
|
|
300
374
|
|
|
@@ -306,15 +380,11 @@ export class MaterialDataManager {
|
|
|
306
380
|
case 'sheenColor':
|
|
307
381
|
if ( value.r !== undefined ) {
|
|
308
382
|
|
|
309
|
-
data
|
|
310
|
-
data[ stride + M.SHEEN_COLOR + 1 ] = value.g;
|
|
311
|
-
data[ stride + M.SHEEN_COLOR + 2 ] = value.b;
|
|
383
|
+
this._writeColor( data, stride + M.SHEEN_COLOR, value.r, value.g, value.b );
|
|
312
384
|
|
|
313
385
|
} else if ( Array.isArray( value ) ) {
|
|
314
386
|
|
|
315
|
-
data
|
|
316
|
-
data[ stride + M.SHEEN_COLOR + 1 ] = value[ 1 ];
|
|
317
|
-
data[ stride + M.SHEEN_COLOR + 2 ] = value[ 2 ];
|
|
387
|
+
this._writeColor( data, stride + M.SHEEN_COLOR, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
318
388
|
|
|
319
389
|
}
|
|
320
390
|
|
|
@@ -323,15 +393,11 @@ export class MaterialDataManager {
|
|
|
323
393
|
case 'specularColor':
|
|
324
394
|
if ( value.r !== undefined ) {
|
|
325
395
|
|
|
326
|
-
data
|
|
327
|
-
data[ stride + M.SPECULAR_COLOR + 1 ] = value.g;
|
|
328
|
-
data[ stride + M.SPECULAR_COLOR + 2 ] = value.b;
|
|
396
|
+
this._writeColor( data, stride + M.SPECULAR_COLOR, value.r, value.g, value.b );
|
|
329
397
|
|
|
330
398
|
} else if ( Array.isArray( value ) ) {
|
|
331
399
|
|
|
332
|
-
data
|
|
333
|
-
data[ stride + M.SPECULAR_COLOR + 1 ] = value[ 1 ];
|
|
334
|
-
data[ stride + M.SPECULAR_COLOR + 2 ] = value[ 2 ];
|
|
400
|
+
this._writeColor( data, stride + M.SPECULAR_COLOR, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
335
401
|
|
|
336
402
|
}
|
|
337
403
|
|
|
@@ -383,15 +449,11 @@ export class MaterialDataManager {
|
|
|
383
449
|
case 'subsurfaceColor':
|
|
384
450
|
if ( value.r !== undefined ) {
|
|
385
451
|
|
|
386
|
-
data
|
|
387
|
-
data[ stride + M.SUBSURFACE_COLOR + 1 ] = value.g;
|
|
388
|
-
data[ stride + M.SUBSURFACE_COLOR + 2 ] = value.b;
|
|
452
|
+
this._writeColor( data, stride + M.SUBSURFACE_COLOR, value.r, value.g, value.b );
|
|
389
453
|
|
|
390
454
|
} else if ( Array.isArray( value ) ) {
|
|
391
455
|
|
|
392
|
-
data
|
|
393
|
-
data[ stride + M.SUBSURFACE_COLOR + 1 ] = value[ 1 ];
|
|
394
|
-
data[ stride + M.SUBSURFACE_COLOR + 2 ] = value[ 2 ];
|
|
456
|
+
this._writeColor( data, stride + M.SUBSURFACE_COLOR, value[ 0 ], value[ 1 ], value[ 2 ] );
|
|
395
457
|
|
|
396
458
|
}
|
|
397
459
|
|
|
@@ -419,6 +481,7 @@ export class MaterialDataManager {
|
|
|
419
481
|
}
|
|
420
482
|
|
|
421
483
|
this.materialStorageAttr.needsUpdate = true;
|
|
484
|
+
( this._hostSet[ materialIndex ] ??= new Set() ).add( property );
|
|
422
485
|
|
|
423
486
|
// Recompute triangle-data opaque-blocker flag when any input to it changes.
|
|
424
487
|
if ( BLOCKER_PROPS.has( property ) ) {
|
|
@@ -434,7 +497,7 @@ export class MaterialDataManager {
|
|
|
434
497
|
/**
|
|
435
498
|
* Bulk-load an entire material object's data into the storage buffer.
|
|
436
499
|
* @param {number} materialIndex
|
|
437
|
-
* @param {Object} materialData
|
|
500
|
+
* @param {Object} materialData - a createMaterialObject() result
|
|
438
501
|
*/
|
|
439
502
|
updateMaterialDataFromObject( materialIndex, materialData ) {
|
|
440
503
|
|
|
@@ -446,167 +509,24 @@ export class MaterialDataManager {
|
|
|
446
509
|
}
|
|
447
510
|
|
|
448
511
|
const data = this.materialStorageAttr.array;
|
|
449
|
-
const
|
|
450
|
-
|
|
451
|
-
if ( materialData.color ) {
|
|
452
|
-
|
|
453
|
-
data[ stride + M.COLOR ] = materialData.color.r ?? materialData.color[ 0 ] ?? 1;
|
|
454
|
-
data[ stride + M.COLOR + 1 ] = materialData.color.g ?? materialData.color[ 1 ] ?? 1;
|
|
455
|
-
data[ stride + M.COLOR + 2 ] = materialData.color.b ?? materialData.color[ 2 ] ?? 1;
|
|
456
|
-
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
data[ stride + M.METALNESS ] = materialData.metalness ?? 0;
|
|
512
|
+
const base = materialIndex * M.FLOATS_PER_MATERIAL;
|
|
513
|
+
packMaterial( data, base, materialData );
|
|
460
514
|
|
|
461
|
-
|
|
515
|
+
// packMaterial writes tints as authored; a whole upload is converted in setMaterialData.
|
|
516
|
+
for ( const offset of MaterialDataManager.COLOR_OFFSETS ) {
|
|
462
517
|
|
|
463
|
-
data[
|
|
464
|
-
data[ stride + M.EMISSIVE + 1 ] = materialData.emissive.g ?? materialData.emissive[ 1 ] ?? 0;
|
|
465
|
-
data[ stride + M.EMISSIVE + 2 ] = materialData.emissive.b ?? materialData.emissive[ 2 ] ?? 0;
|
|
518
|
+
this._writeColor( data, base + offset, data[ base + offset ], data[ base + offset + 1 ], data[ base + offset + 2 ] );
|
|
466
519
|
|
|
467
520
|
}
|
|
468
521
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
data[ stride + M.TRANSMISSION ] = materialData.transmission ?? 0;
|
|
472
|
-
data[ stride + M.THICKNESS ] = materialData.thickness ?? 0.1;
|
|
473
|
-
data[ stride + M.EMISSIVE_INTENSITY ] = materialData.emissiveIntensity ?? 1;
|
|
522
|
+
this._sources[ materialIndex ] = materialData.sources;
|
|
523
|
+
this._hostSet[ materialIndex ] = undefined;
|
|
474
524
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
data[ stride + M.ATTENUATION_COLOR ] = materialData.attenuationColor.r ?? materialData.attenuationColor[ 0 ] ?? 1;
|
|
478
|
-
data[ stride + M.ATTENUATION_COLOR + 1 ] = materialData.attenuationColor.g ?? materialData.attenuationColor[ 1 ] ?? 1;
|
|
479
|
-
data[ stride + M.ATTENUATION_COLOR + 2 ] = materialData.attenuationColor.b ?? materialData.attenuationColor[ 2 ] ?? 1;
|
|
480
|
-
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
data[ stride + M.ATTENUATION_DISTANCE ] = normalizeAttenuationDistance( materialData.attenuationDistance );
|
|
484
|
-
data[ stride + M.DISPERSION ] = materialData.dispersion ?? 0;
|
|
485
|
-
data[ stride + M.VISIBLE ] = 1; // Reserved slot (per-mesh visibility handled at BLAS-pointer level)
|
|
486
|
-
data[ stride + M.SHEEN ] = materialData.sheen ?? 0;
|
|
487
|
-
data[ stride + M.SHEEN_ROUGHNESS ] = materialData.sheenRoughness ?? 1;
|
|
488
|
-
|
|
489
|
-
if ( materialData.sheenColor ) {
|
|
490
|
-
|
|
491
|
-
data[ stride + M.SHEEN_COLOR ] = materialData.sheenColor.r ?? materialData.sheenColor[ 0 ] ?? 0;
|
|
492
|
-
data[ stride + M.SHEEN_COLOR + 1 ] = materialData.sheenColor.g ?? materialData.sheenColor[ 1 ] ?? 0;
|
|
493
|
-
data[ stride + M.SHEEN_COLOR + 2 ] = materialData.sheenColor.b ?? materialData.sheenColor[ 2 ] ?? 0;
|
|
494
|
-
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
data[ stride + M.SPECULAR_INTENSITY ] = materialData.specularIntensity ?? 1;
|
|
498
|
-
|
|
499
|
-
if ( materialData.specularColor ) {
|
|
500
|
-
|
|
501
|
-
data[ stride + M.SPECULAR_COLOR ] = materialData.specularColor.r ?? materialData.specularColor[ 0 ] ?? 1;
|
|
502
|
-
data[ stride + M.SPECULAR_COLOR + 1 ] = materialData.specularColor.g ?? materialData.specularColor[ 1 ] ?? 1;
|
|
503
|
-
data[ stride + M.SPECULAR_COLOR + 2 ] = materialData.specularColor.b ?? materialData.specularColor[ 2 ] ?? 1;
|
|
504
|
-
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
data[ stride + M.IRIDESCENCE ] = materialData.iridescence ?? 0;
|
|
508
|
-
data[ stride + M.IRIDESCENCE_IOR ] = materialData.iridescenceIOR ?? 1.3;
|
|
509
|
-
|
|
510
|
-
if ( materialData.iridescenceThicknessRange ) {
|
|
511
|
-
|
|
512
|
-
data[ stride + M.IRIDESCENCE_THICKNESS_RANGE ] = materialData.iridescenceThicknessRange[ 0 ] ?? 100;
|
|
513
|
-
data[ stride + M.IRIDESCENCE_THICKNESS_RANGE + 1 ] = materialData.iridescenceThicknessRange[ 1 ] ?? 400;
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
data[ stride + M.ALBEDO_MAP_INDEX ] = materialData.map ?? - 1;
|
|
518
|
-
data[ stride + M.NORMAL_MAP_INDEX ] = materialData.normalMap ?? - 1;
|
|
519
|
-
data[ stride + M.ROUGHNESS_MAP_INDEX ] = materialData.roughnessMap ?? - 1;
|
|
520
|
-
data[ stride + M.METALNESS_MAP_INDEX ] = materialData.metalnessMap ?? - 1;
|
|
521
|
-
data[ stride + M.EMISSIVE_MAP_INDEX ] = materialData.emissiveMap ?? - 1;
|
|
522
|
-
data[ stride + M.BUMP_MAP_INDEX ] = materialData.bumpMap ?? - 1;
|
|
523
|
-
|
|
524
|
-
data[ stride + M.CLEARCOAT ] = materialData.clearcoat ?? 0;
|
|
525
|
-
data[ stride + M.CLEARCOAT_ROUGHNESS ] = materialData.clearcoatRoughness ?? 0;
|
|
526
|
-
data[ stride + M.OPACITY ] = materialData.opacity ?? 1;
|
|
527
|
-
data[ stride + M.SIDE ] = materialData.side ?? 0;
|
|
528
|
-
// Mirror side into per-triangle data so BVH traversal avoids a material-buffer read.
|
|
529
|
-
this._patchTriangleSideForMaterial( materialIndex, materialData.side ?? 0 );
|
|
530
|
-
// Recompute shadow-ray opaque-blocker flag (reads alphaMode/transparent/transmission/opacity from buffer).
|
|
525
|
+
// Both read back the block, so they must follow the write.
|
|
526
|
+
this._patchTriangleSideForMaterial( materialIndex, data[ base + M.SIDE ] );
|
|
531
527
|
this._recomputeOpaqueBlockerForMaterial( materialIndex );
|
|
532
|
-
data[ stride + M.TRANSPARENT ] = materialData.transparent ?? 0;
|
|
533
|
-
data[ stride + M.ALPHA_TEST ] = materialData.alphaTest ?? 0;
|
|
534
|
-
data[ stride + M.ALPHA_MODE ] = materialData.alphaMode ?? 0;
|
|
535
|
-
data[ stride + M.DEPTH_WRITE ] = materialData.depthWrite ?? 1;
|
|
536
|
-
data[ stride + M.NORMAL_SCALE ] = materialData.normalScale?.x ?? ( typeof materialData.normalScale === 'number' ? materialData.normalScale : 1 );
|
|
537
|
-
data[ stride + M.NORMAL_SCALE + 1 ] = materialData.normalScale?.y ?? ( typeof materialData.normalScale === 'number' ? materialData.normalScale : 1 );
|
|
538
|
-
data[ stride + M.BUMP_SCALE ] = materialData.bumpScale ?? 1;
|
|
539
|
-
data[ stride + M.DISPLACEMENT_SCALE ] = materialData.displacementScale ?? 1;
|
|
540
|
-
data[ stride + M.DISPLACEMENT_MAP_INDEX ] = materialData.displacementMap ?? - 1;
|
|
541
|
-
|
|
542
|
-
// Subsurface scattering
|
|
543
|
-
data[ stride + M.SUBSURFACE ] = materialData.subsurface ?? 0;
|
|
544
|
-
if ( materialData.subsurfaceColor ) {
|
|
545
|
-
|
|
546
|
-
data[ stride + M.SUBSURFACE_COLOR ] = materialData.subsurfaceColor.r ?? materialData.subsurfaceColor[ 0 ] ?? 1;
|
|
547
|
-
data[ stride + M.SUBSURFACE_COLOR + 1 ] = materialData.subsurfaceColor.g ?? materialData.subsurfaceColor[ 1 ] ?? 1;
|
|
548
|
-
data[ stride + M.SUBSURFACE_COLOR + 2 ] = materialData.subsurfaceColor.b ?? materialData.subsurfaceColor[ 2 ] ?? 1;
|
|
549
|
-
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
if ( materialData.subsurfaceRadius ) {
|
|
553
|
-
|
|
554
|
-
data[ stride + M.SUBSURFACE_RADIUS ] = materialData.subsurfaceRadius[ 0 ] ?? 1;
|
|
555
|
-
data[ stride + M.SUBSURFACE_RADIUS + 1 ] = materialData.subsurfaceRadius[ 1 ] ?? 0.2;
|
|
556
|
-
data[ stride + M.SUBSURFACE_RADIUS + 2 ] = materialData.subsurfaceRadius[ 2 ] ?? 0.1;
|
|
557
|
-
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
data[ stride + M.SUBSURFACE_RADIUS_SCALE ] = materialData.subsurfaceRadiusScale ?? 1;
|
|
561
|
-
data[ stride + M.SUBSURFACE_ANISOTROPY ] = materialData.subsurfaceAnisotropy ?? 0;
|
|
562
|
-
|
|
563
|
-
// Surface specular anisotropy (map index defaults to -1 = none)
|
|
564
|
-
data[ stride + M.ANISOTROPY ] = materialData.anisotropy ?? 0;
|
|
565
|
-
data[ stride + M.ANISOTROPY_ROTATION ] = materialData.anisotropyRotation ?? 0;
|
|
566
|
-
data[ stride + M.ANISOTROPY_MAP_INDEX ] = materialData.anisotropyMap ?? - 1;
|
|
567
|
-
|
|
568
|
-
// Extension-texture map indices (packed bucket index, -1 = none)
|
|
569
|
-
data[ stride + M.TRANSMISSION_MAP_INDEX ] = materialData.transmissionMap ?? - 1;
|
|
570
|
-
data[ stride + M.CLEARCOAT_MAP_INDEX ] = materialData.clearcoatMap ?? - 1;
|
|
571
|
-
data[ stride + M.CLEARCOAT_ROUGHNESS_MAP_INDEX ] = materialData.clearcoatRoughnessMap ?? - 1;
|
|
572
|
-
data[ stride + M.SHEEN_COLOR_MAP_INDEX ] = materialData.sheenColorMap ?? - 1;
|
|
573
|
-
data[ stride + M.SHEEN_ROUGHNESS_MAP_INDEX ] = materialData.sheenRoughnessMap ?? - 1;
|
|
574
|
-
data[ stride + M.IRIDESCENCE_MAP_INDEX ] = materialData.iridescenceMap ?? - 1;
|
|
575
|
-
data[ stride + M.IRIDESCENCE_THICKNESS_MAP_INDEX ] = materialData.iridescenceThicknessMap ?? - 1;
|
|
576
|
-
data[ stride + M.SPECULAR_INTENSITY_MAP_INDEX ] = materialData.specularIntensityMap ?? - 1;
|
|
577
|
-
data[ stride + M.SPECULAR_COLOR_MAP_INDEX ] = materialData.specularColorMap ?? - 1;
|
|
578
|
-
|
|
579
|
-
// Texture transformation matrices (8 floats per slot = matrix elements[0..7];
|
|
580
|
-
// element[8]=1 is reconstructed on the GPU by arrayToMat3, so it is NOT stored —
|
|
581
|
-
// writing a 9th float here would spill into the next slot / subsurfaceColor).
|
|
582
|
-
const identity = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
|
|
583
|
-
const transformEntries = [
|
|
584
|
-
{ key: 'mapMatrix', offset: M.ALBEDO_TRANSFORM },
|
|
585
|
-
{ key: 'normalMapMatrices', offset: M.NORMAL_TRANSFORM },
|
|
586
|
-
{ key: 'roughnessMapMatrices', offset: M.ROUGHNESS_TRANSFORM },
|
|
587
|
-
{ key: 'metalnessMapMatrices', offset: M.METALNESS_TRANSFORM },
|
|
588
|
-
{ key: 'emissiveMapMatrices', offset: M.EMISSIVE_TRANSFORM },
|
|
589
|
-
{ key: 'bumpMapMatrices', offset: M.BUMP_TRANSFORM },
|
|
590
|
-
{ key: 'displacementMapMatrices', offset: M.DISPLACEMENT_TRANSFORM }
|
|
591
|
-
];
|
|
592
|
-
|
|
593
|
-
for ( const { key, offset } of transformEntries ) {
|
|
594
|
-
|
|
595
|
-
const matrix = materialData[ key ] ?? identity;
|
|
596
|
-
for ( let i = 0; i < 8; i ++ ) {
|
|
597
|
-
|
|
598
|
-
if ( stride + offset + i < data.length ) {
|
|
599
|
-
|
|
600
|
-
data[ stride + offset + i ] = matrix[ i ];
|
|
601
|
-
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
}
|
|
607
528
|
|
|
608
529
|
this.materialStorageAttr.needsUpdate = true;
|
|
609
|
-
|
|
610
530
|
this._notifyReset();
|
|
611
531
|
|
|
612
532
|
}
|
|
@@ -625,24 +545,12 @@ export class MaterialDataManager {
|
|
|
625
545
|
// (a genuinely new map → the caller must rebuildMaterials to add it to a bucket array).
|
|
626
546
|
if ( this._srgbTexPacked || this._linearTexPacked ) {
|
|
627
547
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
completeMaterialData.displacementMap = this.getPackedTextureIndex( material.displacementMap, false );
|
|
635
|
-
completeMaterialData.anisotropyMap = this.getPackedTextureIndex( material.anisotropyMap, false );
|
|
636
|
-
// Extension maps — color maps (sheenColor, specularColor) are sRGB; the rest are data (linear)
|
|
637
|
-
completeMaterialData.transmissionMap = this.getPackedTextureIndex( material.transmissionMap, false );
|
|
638
|
-
completeMaterialData.clearcoatMap = this.getPackedTextureIndex( material.clearcoatMap, false );
|
|
639
|
-
completeMaterialData.clearcoatRoughnessMap = this.getPackedTextureIndex( material.clearcoatRoughnessMap, false );
|
|
640
|
-
completeMaterialData.sheenColorMap = this.getPackedTextureIndex( material.sheenColorMap, true );
|
|
641
|
-
completeMaterialData.sheenRoughnessMap = this.getPackedTextureIndex( material.sheenRoughnessMap, false );
|
|
642
|
-
completeMaterialData.iridescenceMap = this.getPackedTextureIndex( material.iridescenceMap, false );
|
|
643
|
-
completeMaterialData.iridescenceThicknessMap = this.getPackedTextureIndex( material.iridescenceThicknessMap, false );
|
|
644
|
-
completeMaterialData.specularIntensityMap = this.getPackedTextureIndex( material.specularIntensityMap, false );
|
|
645
|
-
completeMaterialData.specularColorMap = this.getPackedTextureIndex( material.specularColorMap, true );
|
|
548
|
+
const textures = resolveMaterialTextures( material );
|
|
549
|
+
for ( const [ key, isSrgb ] of TEXTURE_POOLS ) {
|
|
550
|
+
|
|
551
|
+
completeMaterialData[ key ] = this.getPackedTextureIndex( textures[ key ], isSrgb );
|
|
552
|
+
|
|
553
|
+
}
|
|
646
554
|
|
|
647
555
|
}
|
|
648
556
|
|
|
@@ -800,6 +708,8 @@ export class MaterialDataManager {
|
|
|
800
708
|
this.linearBuckets = null;
|
|
801
709
|
this._srgbTexPacked = null;
|
|
802
710
|
this._linearTexPacked = null;
|
|
711
|
+
this._sources = [];
|
|
712
|
+
this._hostSet = [];
|
|
803
713
|
|
|
804
714
|
}
|
|
805
715
|
|
|
@@ -299,6 +299,7 @@ export class UniformManager {
|
|
|
299
299
|
samplingTechniqueUniform.value = DEFAULT_STATE.samplingTechnique;
|
|
300
300
|
|
|
301
301
|
u( 'fireflyThreshold', DEFAULT_STATE.fireflyThreshold, 'float' );
|
|
302
|
+
u( 'shadowTerminatorOffset', DEFAULT_STATE.shadowTerminatorOffset, 'float' );
|
|
302
303
|
|
|
303
304
|
// Emissive
|
|
304
305
|
ub( 'enableEmissiveTriangleSampling', DEFAULT_STATE.enableEmissiveTriangleSampling );
|