rayzee 5.1.0 → 5.2.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 +1 -1
- package/dist/rayzee.es.js +2726 -2577
- package/dist/rayzee.es.js.map +1 -1
- package/dist/rayzee.umd.js +49 -49
- package/dist/rayzee.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/EngineDefaults.js +77 -2
- package/src/PathTracerApp.js +1 -0
- package/src/Pipeline/RenderStage.js +0 -1
- package/src/Processor/AssetLoader.js +2 -5
- package/src/Processor/EquirectHDRInfo.js +42 -5
- package/src/Processor/SceneProcessor.js +2 -2
- package/src/Processor/ShaderBuilder.js +9 -0
- package/src/Processor/TextureCreator.js +25 -10
- package/src/RenderSettings.js +1 -0
- package/src/TSL/BVHTraversal.js +8 -2
- package/src/TSL/Common.js +62 -28
- package/src/TSL/EmissiveSampling.js +3 -4
- package/src/TSL/LightsDirect.js +105 -6
- package/src/TSL/PathTracerCore.js +3 -1
- package/src/TSL/Struct.js +16 -0
- package/src/managers/EnvironmentManager.js +1 -1
- package/src/managers/MaterialDataManager.js +138 -150
- package/src/managers/UniformManager.js +1 -0
package/src/TSL/LightsDirect.js
CHANGED
|
@@ -25,10 +25,11 @@ import {
|
|
|
25
25
|
clamp,
|
|
26
26
|
smoothstep,
|
|
27
27
|
select,
|
|
28
|
+
texture,
|
|
28
29
|
} from 'three/tsl';
|
|
29
30
|
|
|
30
|
-
import { Ray,
|
|
31
|
-
import { PI, TWO_PI, EPSILON, REC709_LUMINANCE_COEFFICIENTS, powerHeuristic,
|
|
31
|
+
import { Ray, ShadowMaterial, HitInfo, DirectionSample, MaterialCache } from './Struct.js';
|
|
32
|
+
import { PI, TWO_PI, EPSILON, REC709_LUMINANCE_COEFFICIENTS, powerHeuristic, getShadowMaterial, getDatafromStorageBuffer } from './Common.js';
|
|
32
33
|
import { fresnelSchlickFloat } from './Fresnel.js';
|
|
33
34
|
import { iorToFresnel0 } from './Fresnel.js';
|
|
34
35
|
import {
|
|
@@ -37,6 +38,33 @@ import {
|
|
|
37
38
|
} from './LightsCore.js';
|
|
38
39
|
import { calculateBeerLawAbsorption, calculateShadowTransmittance } from './MaterialTransmission.js';
|
|
39
40
|
import { RandomValue } from './Random.js';
|
|
41
|
+
import { getTransformedUV } from './TextureSampling.js';
|
|
42
|
+
|
|
43
|
+
// Module-level state for alpha-cutout shadow testing.
|
|
44
|
+
// Set by ShaderBuilder before graph construction (same pattern as _meshVisibilityBuffer in BVHTraversal.js).
|
|
45
|
+
let _shadowAlbedoMaps = null;
|
|
46
|
+
let _enableAlphaShadows = null;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Set the albedo texture array node for alpha-aware shadow rays.
|
|
50
|
+
* Must be called before the shader graph is constructed.
|
|
51
|
+
* @param {TextureNode} maps - TSL texture node for the albedo array
|
|
52
|
+
*/
|
|
53
|
+
export function setShadowAlbedoMaps( maps ) {
|
|
54
|
+
|
|
55
|
+
_shadowAlbedoMaps = maps;
|
|
56
|
+
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Set the runtime uniform node that toggles alpha-cutout shadows.
|
|
61
|
+
* @param {UniformNode} node - TSL int uniform (0 = disabled, 1 = enabled)
|
|
62
|
+
*/
|
|
63
|
+
export function setAlphaShadowsUniform( node ) {
|
|
64
|
+
|
|
65
|
+
_enableAlphaShadows = node;
|
|
66
|
+
|
|
67
|
+
}
|
|
40
68
|
|
|
41
69
|
// ================================================================================
|
|
42
70
|
// SHADOW RAY MATERIAL TRANSPARENCY
|
|
@@ -102,11 +130,82 @@ export const traceShadowRay = Fn( ( [
|
|
|
102
130
|
|
|
103
131
|
} );
|
|
104
132
|
|
|
105
|
-
// Fetch material for the hit surface
|
|
106
|
-
const shadowMaterial =
|
|
133
|
+
// Fetch material for the hit surface (thin reader: 7 slots instead of 27)
|
|
134
|
+
const shadowMaterial = ShadowMaterial.wrap( getShadowMaterial( shadowHit.materialIndex, materialBuffer ) );
|
|
135
|
+
|
|
136
|
+
// ---------------------------------------------------------------
|
|
137
|
+
// Alpha-cutout handling (MASK / BLEND with albedo texture alpha)
|
|
138
|
+
// Gated by runtime uniform + alphaMode check — zero overhead for opaque materials.
|
|
139
|
+
// UV computation deferred here from BVH traversal: barycentrics stored in shadowHit.uv,
|
|
140
|
+
// triangle index in shadowHit.triangleIndex. Actual UV interpolation only when needed.
|
|
141
|
+
// ---------------------------------------------------------------
|
|
142
|
+
const alphaCutout = tslBool( false ).toVar();
|
|
143
|
+
|
|
144
|
+
if ( _enableAlphaShadows ) If( _enableAlphaShadows.equal( int( 1 ) ), () => {
|
|
145
|
+
|
|
146
|
+
// Sample texture alpha once (shared by MASK and BLEND paths).
|
|
147
|
+
// Deferred UV: barycentrics in shadowHit.uv, triangle index in shadowHit.triangleIndex.
|
|
148
|
+
const texAlpha = float( 1.0 ).toVar();
|
|
149
|
+
|
|
150
|
+
if ( _shadowAlbedoMaps ) {
|
|
151
|
+
|
|
152
|
+
If( shadowMaterial.albedoMapIndex.greaterThanEqual( int( 0 ) ), () => {
|
|
153
|
+
|
|
154
|
+
const baryU = shadowHit.uv.x;
|
|
155
|
+
const baryV = shadowHit.uv.y;
|
|
156
|
+
const baryW = float( 1.0 ).sub( baryU ).sub( baryV );
|
|
157
|
+
const TRI_STRIDE = int( 8 );
|
|
158
|
+
const uvData1 = getDatafromStorageBuffer( triangleBuffer, shadowHit.triangleIndex, int( 6 ), TRI_STRIDE );
|
|
159
|
+
const uvData2 = getDatafromStorageBuffer( triangleBuffer, shadowHit.triangleIndex, int( 7 ), TRI_STRIDE );
|
|
160
|
+
const hitUV = uvData1.xy.mul( baryW ).add( uvData1.zw.mul( baryU ) ).add( uvData2.xy.mul( baryV ) );
|
|
161
|
+
const albedoUV = getTransformedUV( { uv: hitUV, transform: shadowMaterial.albedoTransform } );
|
|
162
|
+
texAlpha.assign( texture( _shadowAlbedoMaps, albedoUV ).depth( int( shadowMaterial.albedoMapIndex ) ).a );
|
|
163
|
+
|
|
164
|
+
} );
|
|
165
|
+
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
If( shadowMaterial.alphaMode.equal( int( 1 ) ), () => {
|
|
169
|
+
|
|
170
|
+
// MASK mode: binary alpha cutout
|
|
171
|
+
const effectiveAlpha = shadowMaterial.color.a.mul( texAlpha );
|
|
172
|
+
const cutoff = select( shadowMaterial.alphaTest.greaterThan( 0.0 ), shadowMaterial.alphaTest, float( 0.5 ) );
|
|
173
|
+
If( effectiveAlpha.lessThan( cutoff ), () => {
|
|
174
|
+
|
|
175
|
+
alphaCutout.assign( true );
|
|
176
|
+
|
|
177
|
+
} );
|
|
178
|
+
|
|
179
|
+
} ).ElseIf( shadowMaterial.alphaMode.equal( int( 2 ) ), () => {
|
|
180
|
+
|
|
181
|
+
// BLEND mode: modulate transmittance by alpha
|
|
182
|
+
const blendAlpha = clamp( shadowMaterial.color.a.mul( shadowMaterial.opacity ).mul( texAlpha ), 0.0, 1.0 );
|
|
183
|
+
transmittance.mulAssign( float( 1.0 ).sub( blendAlpha ) );
|
|
184
|
+
|
|
185
|
+
If( transmittance.lessThan( 0.005 ), () => {
|
|
186
|
+
|
|
187
|
+
transmittance.assign( 0.0 );
|
|
188
|
+
Break();
|
|
189
|
+
|
|
190
|
+
} );
|
|
191
|
+
|
|
192
|
+
alphaCutout.assign( true );
|
|
193
|
+
|
|
194
|
+
} );
|
|
195
|
+
|
|
196
|
+
} );
|
|
197
|
+
|
|
198
|
+
// ---------------------------------------------------------------
|
|
199
|
+
// Surface interaction: alpha-skip, transmission, transparent, or opaque
|
|
200
|
+
// ---------------------------------------------------------------
|
|
201
|
+
If( alphaCutout, () => {
|
|
202
|
+
|
|
203
|
+
// Alpha-transparent surface — advance ray past it
|
|
204
|
+
const alphaEps = max( float( 1e-5 ), length( shadowHit.hitPoint ).mul( 1e-6 ) );
|
|
205
|
+
rayOrigin.assign( shadowHit.hitPoint.add( dir.mul( alphaEps ) ) );
|
|
206
|
+
remainingDist.subAssign( shadowHit.dst.add( alphaEps ) );
|
|
107
207
|
|
|
108
|
-
|
|
109
|
-
If( shadowMaterial.transmission.greaterThan( 0.0 ), () => {
|
|
208
|
+
} ).ElseIf( shadowMaterial.transmission.greaterThan( 0.0 ), () => {
|
|
110
209
|
|
|
111
210
|
const entering = dot( dir, shadowHit.normal ).lessThan( 0.0 );
|
|
112
211
|
const N = select( entering, shadowHit.normal, shadowHit.normal.negate() );
|
|
@@ -747,7 +747,9 @@ export const Trace = Fn( ( [
|
|
|
747
747
|
|
|
748
748
|
} );
|
|
749
749
|
|
|
750
|
-
// Get material
|
|
750
|
+
// Get full material (27 reads). Lazy transform loading was tested but regressed
|
|
751
|
+
// textured scenes due to identity-construct + conditional-assign overhead.
|
|
752
|
+
// Shadow rays use getShadowMaterial() (7 reads) — the real bandwidth win.
|
|
751
753
|
const material = RayTracingMaterial.wrap( getMaterial( hitInfo.materialIndex, materialBuffer ) ).toVar();
|
|
752
754
|
|
|
753
755
|
// Tessellation-free displacement — refine intersection with ray-height field marching
|
package/src/TSL/Struct.js
CHANGED
|
@@ -52,6 +52,22 @@ export const RayTracingMaterial = struct( {
|
|
|
52
52
|
iridescenceThicknessRange: 'vec2',
|
|
53
53
|
} );
|
|
54
54
|
|
|
55
|
+
// Lightweight material for shadow ray evaluation — only the fields needed
|
|
56
|
+
// by traceShadowRay (alpha, transmission, transparency, attenuation).
|
|
57
|
+
export const ShadowMaterial = struct( {
|
|
58
|
+
color: 'vec4',
|
|
59
|
+
ior: 'float',
|
|
60
|
+
transmission: 'float',
|
|
61
|
+
attenuationColor: 'vec3',
|
|
62
|
+
attenuationDistance: 'float',
|
|
63
|
+
albedoMapIndex: 'int',
|
|
64
|
+
opacity: 'float',
|
|
65
|
+
transparent: 'bool',
|
|
66
|
+
alphaTest: 'float',
|
|
67
|
+
alphaMode: 'int',
|
|
68
|
+
albedoTransform: 'mat3',
|
|
69
|
+
} );
|
|
70
|
+
|
|
55
71
|
export const Sphere = struct( {
|
|
56
72
|
position: 'vec3',
|
|
57
73
|
radius: 'float',
|
|
@@ -312,7 +312,7 @@ export class EnvironmentManager {
|
|
|
312
312
|
const startTime = performance.now();
|
|
313
313
|
const textureForCDF = this.scene.environment;
|
|
314
314
|
|
|
315
|
-
if ( ! textureForCDF.image
|
|
315
|
+
if ( ! textureForCDF.image ) {
|
|
316
316
|
|
|
317
317
|
this._updateCDFStorageBuffers();
|
|
318
318
|
this.uniforms.set( 'envTotalSum', 0.0 );
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
|
|
10
10
|
import { StorageInstancedBufferAttribute } from 'three/webgpu';
|
|
11
11
|
import { storage } from 'three/tsl';
|
|
12
|
-
import { TEXTURE_CONSTANTS } from '../EngineDefaults.js';
|
|
12
|
+
import { TEXTURE_CONSTANTS, MATERIAL_DATA_LAYOUT as M } from '../EngineDefaults.js';
|
|
13
13
|
|
|
14
|
-
const PIXELS_PER_MATERIAL =
|
|
14
|
+
const PIXELS_PER_MATERIAL = M.SLOTS_PER_MATERIAL;
|
|
15
15
|
|
|
16
16
|
export class MaterialDataManager {
|
|
17
17
|
|
|
@@ -166,139 +166,136 @@ export class MaterialDataManager {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
const data = this.materialStorageAttr.array;
|
|
169
|
-
const
|
|
170
|
-
const dataInEachPixel = TEXTURE_CONSTANTS.RGBA_COMPONENTS;
|
|
171
|
-
const dataLengthPerMaterial = pixelsRequired * dataInEachPixel;
|
|
172
|
-
const stride = materialIndex * dataLengthPerMaterial;
|
|
169
|
+
const stride = materialIndex * M.FLOATS_PER_MATERIAL;
|
|
173
170
|
|
|
174
171
|
switch ( property ) {
|
|
175
172
|
|
|
176
173
|
case 'color':
|
|
177
174
|
if ( value.r !== undefined ) {
|
|
178
175
|
|
|
179
|
-
data[ stride +
|
|
180
|
-
data[ stride + 1 ] = value.g;
|
|
181
|
-
data[ stride + 2 ] = value.b;
|
|
176
|
+
data[ stride + M.COLOR ] = value.r;
|
|
177
|
+
data[ stride + M.COLOR + 1 ] = value.g;
|
|
178
|
+
data[ stride + M.COLOR + 2 ] = value.b;
|
|
182
179
|
|
|
183
180
|
} else if ( Array.isArray( value ) ) {
|
|
184
181
|
|
|
185
|
-
data[ stride +
|
|
186
|
-
data[ stride + 1 ] = value[ 1 ];
|
|
187
|
-
data[ stride + 2 ] = value[ 2 ];
|
|
182
|
+
data[ stride + M.COLOR ] = value[ 0 ];
|
|
183
|
+
data[ stride + M.COLOR + 1 ] = value[ 1 ];
|
|
184
|
+
data[ stride + M.COLOR + 2 ] = value[ 2 ];
|
|
188
185
|
|
|
189
186
|
}
|
|
190
187
|
|
|
191
188
|
break;
|
|
192
|
-
case 'metalness': data[ stride +
|
|
189
|
+
case 'metalness': data[ stride + M.METALNESS ] = value; break;
|
|
193
190
|
case 'emissive':
|
|
194
191
|
if ( value.r !== undefined ) {
|
|
195
192
|
|
|
196
|
-
data[ stride +
|
|
197
|
-
data[ stride +
|
|
198
|
-
data[ stride +
|
|
193
|
+
data[ stride + M.EMISSIVE ] = value.r;
|
|
194
|
+
data[ stride + M.EMISSIVE + 1 ] = value.g;
|
|
195
|
+
data[ stride + M.EMISSIVE + 2 ] = value.b;
|
|
199
196
|
|
|
200
197
|
} else if ( Array.isArray( value ) ) {
|
|
201
198
|
|
|
202
|
-
data[ stride +
|
|
203
|
-
data[ stride +
|
|
204
|
-
data[ stride +
|
|
199
|
+
data[ stride + M.EMISSIVE ] = value[ 0 ];
|
|
200
|
+
data[ stride + M.EMISSIVE + 1 ] = value[ 1 ];
|
|
201
|
+
data[ stride + M.EMISSIVE + 2 ] = value[ 2 ];
|
|
205
202
|
|
|
206
203
|
}
|
|
207
204
|
|
|
208
205
|
break;
|
|
209
|
-
case 'roughness': data[ stride +
|
|
210
|
-
case 'ior': data[ stride +
|
|
211
|
-
case 'transmission': data[ stride +
|
|
212
|
-
case 'thickness': data[ stride +
|
|
213
|
-
case 'emissiveIntensity': data[ stride +
|
|
206
|
+
case 'roughness': data[ stride + M.ROUGHNESS ] = value; break;
|
|
207
|
+
case 'ior': data[ stride + M.IOR ] = value; break;
|
|
208
|
+
case 'transmission': data[ stride + M.TRANSMISSION ] = value; break;
|
|
209
|
+
case 'thickness': data[ stride + M.THICKNESS ] = value; break;
|
|
210
|
+
case 'emissiveIntensity': data[ stride + M.EMISSIVE_INTENSITY ] = value; break;
|
|
214
211
|
case 'attenuationColor':
|
|
215
212
|
if ( value.r !== undefined ) {
|
|
216
213
|
|
|
217
|
-
data[ stride +
|
|
218
|
-
data[ stride +
|
|
219
|
-
data[ stride +
|
|
214
|
+
data[ stride + M.ATTENUATION_COLOR ] = value.r;
|
|
215
|
+
data[ stride + M.ATTENUATION_COLOR + 1 ] = value.g;
|
|
216
|
+
data[ stride + M.ATTENUATION_COLOR + 2 ] = value.b;
|
|
220
217
|
|
|
221
218
|
} else if ( Array.isArray( value ) ) {
|
|
222
219
|
|
|
223
|
-
data[ stride +
|
|
224
|
-
data[ stride +
|
|
225
|
-
data[ stride +
|
|
220
|
+
data[ stride + M.ATTENUATION_COLOR ] = value[ 0 ];
|
|
221
|
+
data[ stride + M.ATTENUATION_COLOR + 1 ] = value[ 1 ];
|
|
222
|
+
data[ stride + M.ATTENUATION_COLOR + 2 ] = value[ 2 ];
|
|
226
223
|
|
|
227
224
|
}
|
|
228
225
|
|
|
229
226
|
break;
|
|
230
|
-
case 'attenuationDistance': data[ stride +
|
|
231
|
-
case 'dispersion': data[ stride +
|
|
232
|
-
case 'sheen': data[ stride +
|
|
233
|
-
case 'sheenRoughness': data[ stride +
|
|
227
|
+
case 'attenuationDistance': data[ stride + M.ATTENUATION_DISTANCE ] = value; break;
|
|
228
|
+
case 'dispersion': data[ stride + M.DISPERSION ] = value; break;
|
|
229
|
+
case 'sheen': data[ stride + M.SHEEN ] = value; break;
|
|
230
|
+
case 'sheenRoughness': data[ stride + M.SHEEN_ROUGHNESS ] = value; break;
|
|
234
231
|
case 'sheenColor':
|
|
235
232
|
if ( value.r !== undefined ) {
|
|
236
233
|
|
|
237
|
-
data[ stride +
|
|
238
|
-
data[ stride +
|
|
239
|
-
data[ stride +
|
|
234
|
+
data[ stride + M.SHEEN_COLOR ] = value.r;
|
|
235
|
+
data[ stride + M.SHEEN_COLOR + 1 ] = value.g;
|
|
236
|
+
data[ stride + M.SHEEN_COLOR + 2 ] = value.b;
|
|
240
237
|
|
|
241
238
|
} else if ( Array.isArray( value ) ) {
|
|
242
239
|
|
|
243
|
-
data[ stride +
|
|
244
|
-
data[ stride +
|
|
245
|
-
data[ stride +
|
|
240
|
+
data[ stride + M.SHEEN_COLOR ] = value[ 0 ];
|
|
241
|
+
data[ stride + M.SHEEN_COLOR + 1 ] = value[ 1 ];
|
|
242
|
+
data[ stride + M.SHEEN_COLOR + 2 ] = value[ 2 ];
|
|
246
243
|
|
|
247
244
|
}
|
|
248
245
|
|
|
249
246
|
break;
|
|
250
|
-
case 'specularIntensity': data[ stride +
|
|
247
|
+
case 'specularIntensity': data[ stride + M.SPECULAR_INTENSITY ] = value; break;
|
|
251
248
|
case 'specularColor':
|
|
252
249
|
if ( value.r !== undefined ) {
|
|
253
250
|
|
|
254
|
-
data[ stride +
|
|
255
|
-
data[ stride +
|
|
256
|
-
data[ stride +
|
|
251
|
+
data[ stride + M.SPECULAR_COLOR ] = value.r;
|
|
252
|
+
data[ stride + M.SPECULAR_COLOR + 1 ] = value.g;
|
|
253
|
+
data[ stride + M.SPECULAR_COLOR + 2 ] = value.b;
|
|
257
254
|
|
|
258
255
|
} else if ( Array.isArray( value ) ) {
|
|
259
256
|
|
|
260
|
-
data[ stride +
|
|
261
|
-
data[ stride +
|
|
262
|
-
data[ stride +
|
|
257
|
+
data[ stride + M.SPECULAR_COLOR ] = value[ 0 ];
|
|
258
|
+
data[ stride + M.SPECULAR_COLOR + 1 ] = value[ 1 ];
|
|
259
|
+
data[ stride + M.SPECULAR_COLOR + 2 ] = value[ 2 ];
|
|
263
260
|
|
|
264
261
|
}
|
|
265
262
|
|
|
266
263
|
break;
|
|
267
|
-
case 'iridescence': data[ stride +
|
|
268
|
-
case 'iridescenceIOR': data[ stride +
|
|
264
|
+
case 'iridescence': data[ stride + M.IRIDESCENCE ] = value; break;
|
|
265
|
+
case 'iridescenceIOR': data[ stride + M.IRIDESCENCE_IOR ] = value; break;
|
|
269
266
|
case 'iridescenceThicknessRange':
|
|
270
267
|
if ( Array.isArray( value ) ) {
|
|
271
268
|
|
|
272
|
-
data[ stride +
|
|
273
|
-
data[ stride +
|
|
269
|
+
data[ stride + M.IRIDESCENCE_THICKNESS_RANGE ] = value[ 0 ];
|
|
270
|
+
data[ stride + M.IRIDESCENCE_THICKNESS_RANGE + 1 ] = value[ 1 ];
|
|
274
271
|
|
|
275
272
|
}
|
|
276
273
|
|
|
277
274
|
break;
|
|
278
|
-
case 'clearcoat': data[ stride +
|
|
279
|
-
case 'clearcoatRoughness': data[ stride +
|
|
280
|
-
case 'opacity': data[ stride +
|
|
281
|
-
case 'side': data[ stride +
|
|
282
|
-
case 'transparent': data[ stride +
|
|
283
|
-
case 'alphaTest': data[ stride +
|
|
284
|
-
case 'alphaMode': data[ stride +
|
|
285
|
-
case 'depthWrite': data[ stride +
|
|
275
|
+
case 'clearcoat': data[ stride + M.CLEARCOAT ] = value; break;
|
|
276
|
+
case 'clearcoatRoughness': data[ stride + M.CLEARCOAT_ROUGHNESS ] = value; break;
|
|
277
|
+
case 'opacity': data[ stride + M.OPACITY ] = value; break;
|
|
278
|
+
case 'side': data[ stride + M.SIDE ] = value; break;
|
|
279
|
+
case 'transparent': data[ stride + M.TRANSPARENT ] = value; break;
|
|
280
|
+
case 'alphaTest': data[ stride + M.ALPHA_TEST ] = value; break;
|
|
281
|
+
case 'alphaMode': data[ stride + M.ALPHA_MODE ] = value; break;
|
|
282
|
+
case 'depthWrite': data[ stride + M.DEPTH_WRITE ] = value; break;
|
|
286
283
|
case 'normalScale':
|
|
287
284
|
if ( value.x !== undefined ) {
|
|
288
285
|
|
|
289
|
-
data[ stride +
|
|
290
|
-
data[ stride +
|
|
286
|
+
data[ stride + M.NORMAL_SCALE ] = value.x;
|
|
287
|
+
data[ stride + M.NORMAL_SCALE + 1 ] = value.y;
|
|
291
288
|
|
|
292
289
|
} else if ( typeof value === 'number' ) {
|
|
293
290
|
|
|
294
|
-
data[ stride +
|
|
295
|
-
data[ stride +
|
|
291
|
+
data[ stride + M.NORMAL_SCALE ] = value;
|
|
292
|
+
data[ stride + M.NORMAL_SCALE + 1 ] = value;
|
|
296
293
|
|
|
297
294
|
}
|
|
298
295
|
|
|
299
296
|
break;
|
|
300
|
-
case 'bumpScale': data[ stride +
|
|
301
|
-
case 'displacementScale': data[ stride +
|
|
297
|
+
case 'bumpScale': data[ stride + M.BUMP_SCALE ] = value; break;
|
|
298
|
+
case 'displacementScale': data[ stride + M.DISPLACEMENT_SCALE ] = value; break;
|
|
302
299
|
default:
|
|
303
300
|
console.warn( `Unknown material property: ${property}` );
|
|
304
301
|
return;
|
|
@@ -338,108 +335,105 @@ export class MaterialDataManager {
|
|
|
338
335
|
}
|
|
339
336
|
|
|
340
337
|
const data = this.materialStorageAttr.array;
|
|
341
|
-
const
|
|
342
|
-
const dataInEachPixel = TEXTURE_CONSTANTS.RGBA_COMPONENTS;
|
|
343
|
-
const dataLengthPerMaterial = pixelsRequired * dataInEachPixel;
|
|
344
|
-
const stride = materialIndex * dataLengthPerMaterial;
|
|
338
|
+
const stride = materialIndex * M.FLOATS_PER_MATERIAL;
|
|
345
339
|
|
|
346
340
|
if ( materialData.color ) {
|
|
347
341
|
|
|
348
|
-
data[ stride +
|
|
349
|
-
data[ stride + 1 ] = materialData.color.g ?? materialData.color[ 1 ] ?? 1;
|
|
350
|
-
data[ stride + 2 ] = materialData.color.b ?? materialData.color[ 2 ] ?? 1;
|
|
342
|
+
data[ stride + M.COLOR ] = materialData.color.r ?? materialData.color[ 0 ] ?? 1;
|
|
343
|
+
data[ stride + M.COLOR + 1 ] = materialData.color.g ?? materialData.color[ 1 ] ?? 1;
|
|
344
|
+
data[ stride + M.COLOR + 2 ] = materialData.color.b ?? materialData.color[ 2 ] ?? 1;
|
|
351
345
|
|
|
352
346
|
}
|
|
353
347
|
|
|
354
|
-
data[ stride +
|
|
348
|
+
data[ stride + M.METALNESS ] = materialData.metalness ?? 0;
|
|
355
349
|
|
|
356
350
|
if ( materialData.emissive ) {
|
|
357
351
|
|
|
358
|
-
data[ stride +
|
|
359
|
-
data[ stride +
|
|
360
|
-
data[ stride +
|
|
352
|
+
data[ stride + M.EMISSIVE ] = materialData.emissive.r ?? materialData.emissive[ 0 ] ?? 0;
|
|
353
|
+
data[ stride + M.EMISSIVE + 1 ] = materialData.emissive.g ?? materialData.emissive[ 1 ] ?? 0;
|
|
354
|
+
data[ stride + M.EMISSIVE + 2 ] = materialData.emissive.b ?? materialData.emissive[ 2 ] ?? 0;
|
|
361
355
|
|
|
362
356
|
}
|
|
363
357
|
|
|
364
|
-
data[ stride +
|
|
365
|
-
data[ stride +
|
|
366
|
-
data[ stride +
|
|
367
|
-
data[ stride +
|
|
368
|
-
data[ stride +
|
|
358
|
+
data[ stride + M.ROUGHNESS ] = materialData.roughness ?? 1;
|
|
359
|
+
data[ stride + M.IOR ] = materialData.ior ?? 1.5;
|
|
360
|
+
data[ stride + M.TRANSMISSION ] = materialData.transmission ?? 0;
|
|
361
|
+
data[ stride + M.THICKNESS ] = materialData.thickness ?? 0.1;
|
|
362
|
+
data[ stride + M.EMISSIVE_INTENSITY ] = materialData.emissiveIntensity ?? 1;
|
|
369
363
|
|
|
370
364
|
if ( materialData.attenuationColor ) {
|
|
371
365
|
|
|
372
|
-
data[ stride +
|
|
373
|
-
data[ stride +
|
|
374
|
-
data[ stride +
|
|
366
|
+
data[ stride + M.ATTENUATION_COLOR ] = materialData.attenuationColor.r ?? materialData.attenuationColor[ 0 ] ?? 1;
|
|
367
|
+
data[ stride + M.ATTENUATION_COLOR + 1 ] = materialData.attenuationColor.g ?? materialData.attenuationColor[ 1 ] ?? 1;
|
|
368
|
+
data[ stride + M.ATTENUATION_COLOR + 2 ] = materialData.attenuationColor.b ?? materialData.attenuationColor[ 2 ] ?? 1;
|
|
375
369
|
|
|
376
370
|
}
|
|
377
371
|
|
|
378
|
-
data[ stride +
|
|
379
|
-
data[ stride +
|
|
380
|
-
data[ stride +
|
|
381
|
-
data[ stride +
|
|
382
|
-
data[ stride +
|
|
372
|
+
data[ stride + M.ATTENUATION_DISTANCE ] = materialData.attenuationDistance ?? Infinity;
|
|
373
|
+
data[ stride + M.DISPERSION ] = materialData.dispersion ?? 0;
|
|
374
|
+
data[ stride + M.VISIBLE ] = 1; // Reserved slot (per-mesh visibility handled at BLAS-pointer level)
|
|
375
|
+
data[ stride + M.SHEEN ] = materialData.sheen ?? 0;
|
|
376
|
+
data[ stride + M.SHEEN_ROUGHNESS ] = materialData.sheenRoughness ?? 1;
|
|
383
377
|
|
|
384
378
|
if ( materialData.sheenColor ) {
|
|
385
379
|
|
|
386
|
-
data[ stride +
|
|
387
|
-
data[ stride +
|
|
388
|
-
data[ stride +
|
|
380
|
+
data[ stride + M.SHEEN_COLOR ] = materialData.sheenColor.r ?? materialData.sheenColor[ 0 ] ?? 0;
|
|
381
|
+
data[ stride + M.SHEEN_COLOR + 1 ] = materialData.sheenColor.g ?? materialData.sheenColor[ 1 ] ?? 0;
|
|
382
|
+
data[ stride + M.SHEEN_COLOR + 2 ] = materialData.sheenColor.b ?? materialData.sheenColor[ 2 ] ?? 0;
|
|
389
383
|
|
|
390
384
|
}
|
|
391
385
|
|
|
392
|
-
data[ stride +
|
|
386
|
+
data[ stride + M.SPECULAR_INTENSITY ] = materialData.specularIntensity ?? 1;
|
|
393
387
|
|
|
394
388
|
if ( materialData.specularColor ) {
|
|
395
389
|
|
|
396
|
-
data[ stride +
|
|
397
|
-
data[ stride +
|
|
398
|
-
data[ stride +
|
|
390
|
+
data[ stride + M.SPECULAR_COLOR ] = materialData.specularColor.r ?? materialData.specularColor[ 0 ] ?? 1;
|
|
391
|
+
data[ stride + M.SPECULAR_COLOR + 1 ] = materialData.specularColor.g ?? materialData.specularColor[ 1 ] ?? 1;
|
|
392
|
+
data[ stride + M.SPECULAR_COLOR + 2 ] = materialData.specularColor.b ?? materialData.specularColor[ 2 ] ?? 1;
|
|
399
393
|
|
|
400
394
|
}
|
|
401
395
|
|
|
402
|
-
data[ stride +
|
|
403
|
-
data[ stride +
|
|
396
|
+
data[ stride + M.IRIDESCENCE ] = materialData.iridescence ?? 0;
|
|
397
|
+
data[ stride + M.IRIDESCENCE_IOR ] = materialData.iridescenceIOR ?? 1.3;
|
|
404
398
|
|
|
405
399
|
if ( materialData.iridescenceThicknessRange ) {
|
|
406
400
|
|
|
407
|
-
data[ stride +
|
|
408
|
-
data[ stride +
|
|
401
|
+
data[ stride + M.IRIDESCENCE_THICKNESS_RANGE ] = materialData.iridescenceThicknessRange[ 0 ] ?? 100;
|
|
402
|
+
data[ stride + M.IRIDESCENCE_THICKNESS_RANGE + 1 ] = materialData.iridescenceThicknessRange[ 1 ] ?? 400;
|
|
409
403
|
|
|
410
404
|
}
|
|
411
405
|
|
|
412
|
-
data[ stride +
|
|
413
|
-
data[ stride +
|
|
414
|
-
data[ stride +
|
|
415
|
-
data[ stride +
|
|
416
|
-
data[ stride +
|
|
417
|
-
data[ stride +
|
|
418
|
-
|
|
419
|
-
data[ stride +
|
|
420
|
-
data[ stride +
|
|
421
|
-
data[ stride +
|
|
422
|
-
data[ stride +
|
|
423
|
-
data[ stride +
|
|
424
|
-
data[ stride +
|
|
425
|
-
data[ stride +
|
|
426
|
-
data[ stride +
|
|
427
|
-
data[ stride +
|
|
428
|
-
data[ stride +
|
|
429
|
-
data[ stride +
|
|
430
|
-
data[ stride +
|
|
431
|
-
data[ stride +
|
|
406
|
+
data[ stride + M.ALBEDO_MAP_INDEX ] = materialData.map ?? - 1;
|
|
407
|
+
data[ stride + M.NORMAL_MAP_INDEX ] = materialData.normalMap ?? - 1;
|
|
408
|
+
data[ stride + M.ROUGHNESS_MAP_INDEX ] = materialData.roughnessMap ?? - 1;
|
|
409
|
+
data[ stride + M.METALNESS_MAP_INDEX ] = materialData.metalnessMap ?? - 1;
|
|
410
|
+
data[ stride + M.EMISSIVE_MAP_INDEX ] = materialData.emissiveMap ?? - 1;
|
|
411
|
+
data[ stride + M.BUMP_MAP_INDEX ] = materialData.bumpMap ?? - 1;
|
|
412
|
+
|
|
413
|
+
data[ stride + M.CLEARCOAT ] = materialData.clearcoat ?? 0;
|
|
414
|
+
data[ stride + M.CLEARCOAT_ROUGHNESS ] = materialData.clearcoatRoughness ?? 0;
|
|
415
|
+
data[ stride + M.OPACITY ] = materialData.opacity ?? 1;
|
|
416
|
+
data[ stride + M.SIDE ] = materialData.side ?? 0;
|
|
417
|
+
data[ stride + M.TRANSPARENT ] = materialData.transparent ?? 0;
|
|
418
|
+
data[ stride + M.ALPHA_TEST ] = materialData.alphaTest ?? 0;
|
|
419
|
+
data[ stride + M.ALPHA_MODE ] = materialData.alphaMode ?? 0;
|
|
420
|
+
data[ stride + M.DEPTH_WRITE ] = materialData.depthWrite ?? 1;
|
|
421
|
+
data[ stride + M.NORMAL_SCALE ] = materialData.normalScale?.x ?? ( typeof materialData.normalScale === 'number' ? materialData.normalScale : 1 );
|
|
422
|
+
data[ stride + M.NORMAL_SCALE + 1 ] = materialData.normalScale?.y ?? ( typeof materialData.normalScale === 'number' ? materialData.normalScale : 1 );
|
|
423
|
+
data[ stride + M.BUMP_SCALE ] = materialData.bumpScale ?? 1;
|
|
424
|
+
data[ stride + M.DISPLACEMENT_SCALE ] = materialData.displacementScale ?? 1;
|
|
425
|
+
data[ stride + M.DISPLACEMENT_MAP_INDEX ] = materialData.displacementMap ?? - 1;
|
|
432
426
|
|
|
433
427
|
// Texture transformation matrices (9 floats each, identity if missing)
|
|
434
428
|
const identity = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
|
|
435
429
|
const transformEntries = [
|
|
436
|
-
{ key: 'mapMatrix', offset:
|
|
437
|
-
{ key: 'normalMapMatrices', offset:
|
|
438
|
-
{ key: 'roughnessMapMatrices', offset:
|
|
439
|
-
{ key: 'metalnessMapMatrices', offset:
|
|
440
|
-
{ key: 'emissiveMapMatrices', offset:
|
|
441
|
-
{ key: 'bumpMapMatrices', offset:
|
|
442
|
-
{ key: 'displacementMapMatrices', offset:
|
|
430
|
+
{ key: 'mapMatrix', offset: M.ALBEDO_TRANSFORM },
|
|
431
|
+
{ key: 'normalMapMatrices', offset: M.NORMAL_TRANSFORM },
|
|
432
|
+
{ key: 'roughnessMapMatrices', offset: M.ROUGHNESS_TRANSFORM },
|
|
433
|
+
{ key: 'metalnessMapMatrices', offset: M.METALNESS_TRANSFORM },
|
|
434
|
+
{ key: 'emissiveMapMatrices', offset: M.EMISSIVE_TRANSFORM },
|
|
435
|
+
{ key: 'bumpMapMatrices', offset: M.BUMP_TRANSFORM },
|
|
436
|
+
{ key: 'displacementMapMatrices', offset: M.DISPLACEMENT_TRANSFORM }
|
|
443
437
|
];
|
|
444
438
|
|
|
445
439
|
for ( const { key, offset } of transformEntries ) {
|
|
@@ -497,20 +491,17 @@ export class MaterialDataManager {
|
|
|
497
491
|
|
|
498
492
|
}
|
|
499
493
|
|
|
500
|
-
const pixelsRequired = TEXTURE_CONSTANTS.PIXELS_PER_MATERIAL;
|
|
501
|
-
const dataInEachPixel = TEXTURE_CONSTANTS.RGBA_COMPONENTS;
|
|
502
|
-
const dataLengthPerMaterial = pixelsRequired * dataInEachPixel;
|
|
503
494
|
const data = this.materialStorageAttr.array;
|
|
504
|
-
const stride = materialIndex *
|
|
495
|
+
const stride = materialIndex * M.FLOATS_PER_MATERIAL;
|
|
505
496
|
|
|
506
497
|
const transformOffsets = {
|
|
507
|
-
'map':
|
|
508
|
-
'normalMap':
|
|
509
|
-
'roughnessMap':
|
|
510
|
-
'metalnessMap':
|
|
511
|
-
'emissiveMap':
|
|
512
|
-
'bumpMap':
|
|
513
|
-
'displacementMap':
|
|
498
|
+
'map': M.ALBEDO_TRANSFORM,
|
|
499
|
+
'normalMap': M.NORMAL_TRANSFORM,
|
|
500
|
+
'roughnessMap': M.ROUGHNESS_TRANSFORM,
|
|
501
|
+
'metalnessMap': M.METALNESS_TRANSFORM,
|
|
502
|
+
'emissiveMap': M.EMISSIVE_TRANSFORM,
|
|
503
|
+
'bumpMap': M.BUMP_TRANSFORM,
|
|
504
|
+
'displacementMap': M.DISPLACEMENT_TRANSFORM
|
|
514
505
|
};
|
|
515
506
|
|
|
516
507
|
const offset = transformOffsets[ textureName ];
|
|
@@ -552,9 +543,6 @@ export class MaterialDataManager {
|
|
|
552
543
|
}
|
|
553
544
|
|
|
554
545
|
const data = this.materialStorageAttr.array;
|
|
555
|
-
const pixelsRequired = TEXTURE_CONSTANTS.PIXELS_PER_MATERIAL;
|
|
556
|
-
const dataInEachPixel = TEXTURE_CONSTANTS.RGBA_COMPONENTS;
|
|
557
|
-
const dataLengthPerMaterial = pixelsRequired * dataInEachPixel;
|
|
558
546
|
const materialCount = this.sdfs.materialCount || 1;
|
|
559
547
|
|
|
560
548
|
const newFeatures = {
|
|
@@ -570,16 +558,16 @@ export class MaterialDataManager {
|
|
|
570
558
|
|
|
571
559
|
for ( let i = 0; i < materialCount; i ++ ) {
|
|
572
560
|
|
|
573
|
-
const stride = i *
|
|
561
|
+
const stride = i * M.FLOATS_PER_MATERIAL;
|
|
574
562
|
|
|
575
|
-
const transmission = data[ stride +
|
|
576
|
-
const dispersion = data[ stride +
|
|
577
|
-
const sheen = data[ stride +
|
|
578
|
-
const iridescence = data[ stride +
|
|
579
|
-
const clearcoat = data[ stride +
|
|
580
|
-
const opacity = data[ stride +
|
|
581
|
-
const transparent = data[ stride +
|
|
582
|
-
const alphaTest = data[ stride +
|
|
563
|
+
const transmission = data[ stride + M.TRANSMISSION ];
|
|
564
|
+
const dispersion = data[ stride + M.DISPERSION ];
|
|
565
|
+
const sheen = data[ stride + M.SHEEN ];
|
|
566
|
+
const iridescence = data[ stride + M.IRIDESCENCE ];
|
|
567
|
+
const clearcoat = data[ stride + M.CLEARCOAT ];
|
|
568
|
+
const opacity = data[ stride + M.OPACITY ];
|
|
569
|
+
const transparent = data[ stride + M.TRANSPARENT ];
|
|
570
|
+
const alphaTest = data[ stride + M.ALPHA_TEST ];
|
|
583
571
|
|
|
584
572
|
if ( clearcoat > 0 ) newFeatures.hasClearcoat = true;
|
|
585
573
|
if ( transmission > 0 ) newFeatures.hasTransmission = true;
|
|
@@ -240,6 +240,7 @@ export class UniformManager {
|
|
|
240
240
|
|
|
241
241
|
// Render mode
|
|
242
242
|
u( 'renderMode', DEFAULT_STATE.renderMode, 'int' );
|
|
243
|
+
ub( 'enableAlphaShadows', DEFAULT_STATE.enableAlphaShadows );
|
|
243
244
|
|
|
244
245
|
// Resolution (for RNG seeding)
|
|
245
246
|
u( 'resolution', new Vector2( width, height ), 'vec2' );
|