three-gpu-pathtracer 0.0.23 → 0.0.25
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 +53 -528
- package/build/index.module.js +319 -66
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +318 -64
- package/build/index.umd.cjs.map +1 -1
- package/package.json +35 -18
- package/src/core/PathTracingSceneGenerator.js +21 -2
- package/src/core/WebGLPathTracer.js +16 -7
- package/src/core/utils/mergeGeometries.js +14 -1
- package/src/core/utils/sceneUpdateUtils.js +8 -12
- package/src/detectors/PrecisionMaterial.js +9 -9
- package/src/index.d.ts +2 -1
- package/src/index.js +1 -0
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +2 -1
- package/src/materials/pathtracing/glsl/attenuate_hit_function.glsl.js +2 -1
- package/src/materials/pathtracing/glsl/camera_util_functions.glsl.js +1 -1
- package/src/materials/pathtracing/glsl/get_surface_record_function.glsl.js +2 -1
- package/src/materials/surface/AmbientOcclusionMaterial.js +2 -0
- package/src/objects/PhysicalSpotLight.js +2 -0
- package/src/shader/bsdf/bsdf_functions.glsl.js +0 -1
- package/src/shader/bvh/inside_fog_volume_function.glsl.js +1 -1
- package/src/shader/structs/material_struct.glsl.js +3 -1
- package/src/textures/BlueNoiseTexture.js +6 -6
- package/src/textures/ProceduralEquirectTexture.js +8 -7
- package/src/textures/turquinMetal.png +0 -0
- package/src/uniforms/EquirectHdrInfoUniform.js +9 -4
- package/src/uniforms/FloatAttributeTextureArray.js +11 -11
- package/src/uniforms/MaterialsTexture.js +13 -10
- package/src/webgpu/API.md +762 -0
- package/src/webgpu/AtlasTexture.js +471 -0
- package/src/webgpu/BlurredEnvMapGenerator.js +129 -0
- package/src/webgpu/EquirectBackgroundInfo.js +97 -0
- package/src/webgpu/EquirectHdrInfoNode.js +151 -0
- package/src/webgpu/LightsInfoNode.js +224 -0
- package/src/webgpu/MegaKernelPathTracer.js +277 -0
- package/src/webgpu/PathTracerBackend.js +216 -0
- package/src/webgpu/TurquinTexture.js +169 -0
- package/src/webgpu/WaveFrontPathTracer.js +586 -0
- package/src/webgpu/WebGPUPathTracer.js +1302 -0
- package/src/webgpu/compute/ComputeKernel.js +92 -0
- package/src/webgpu/compute/CopyBufferKernel.js +40 -0
- package/src/webgpu/compute/PathTracerMegaKernel.js +470 -0
- package/src/webgpu/compute/SampleDebugKernel.js +51 -0
- package/src/webgpu/compute/TallySampleCountsKernel.js +111 -0
- package/src/webgpu/compute/ZeroOutBufferKernel.js +35 -0
- package/src/webgpu/compute/ZeroOutKernel.js +31 -0
- package/src/webgpu/compute/wavefront/LogicKernel.js +349 -0
- package/src/webgpu/compute/wavefront/MaterialKernel.js +371 -0
- package/src/webgpu/compute/wavefront/PopulatePixelIndicesKernel.js +72 -0
- package/src/webgpu/compute/wavefront/QueueLengthToDispatchKernel.js +38 -0
- package/src/webgpu/compute/wavefront/ResetSlotsKernel.js +66 -0
- package/src/webgpu/compute/wavefront/TraceRayKernel.js +71 -0
- package/src/webgpu/compute/wavefront/TraceShadowRayKernel.js +67 -0
- package/src/webgpu/compute/wavefront/structs.js +155 -0
- package/src/webgpu/constants.js +62 -0
- package/src/webgpu/denoise/OIDNDenoiser.js +431 -0
- package/src/webgpu/index.d.ts +176 -0
- package/src/webgpu/index.js +11 -0
- package/src/webgpu/materials/GltfCompliantMaterial.js +608 -0
- package/src/webgpu/materials/GraphMaterial.js +331 -0
- package/src/webgpu/materials/PathtracingMaterial.js +89 -0
- package/src/webgpu/materials/RenderToScreenMaterial.js +150 -0
- package/src/webgpu/materials/debug/AtlasDebugMaterial.js +41 -0
- package/src/webgpu/materials/debug/SampleDensityMaterial.js +61 -0
- package/src/webgpu/nodes/PathtracerBVHComputeData.js +1037 -0
- package/src/webgpu/nodes/debugBounds.wgsl.js +228 -0
- package/src/webgpu/nodes/eon.wgsl.js +262 -0
- package/src/webgpu/nodes/ggx.wgsl.js +190 -0
- package/src/webgpu/nodes/lights.wgsl.js +203 -0
- package/src/webgpu/nodes/material.wgsl.js +990 -0
- package/src/webgpu/nodes/rand/bluedither.wgsl.js +92 -0
- package/src/webgpu/nodes/rand/pcg.wgsl.js +81 -0
- package/src/webgpu/nodes/rand/sobol.wgsl.js +287 -0
- package/src/webgpu/nodes/random.wgsl.js +20 -0
- package/src/webgpu/nodes/reset.wgsl.js +21 -0
- package/src/webgpu/nodes/sampling.wgsl.js +193 -0
- package/src/webgpu/nodes/sheen.wgsl.js +148 -0
- package/src/webgpu/nodes/structs.wgsl.js +272 -0
- package/src/webgpu/nodes/utils.wgsl.js +366 -0
- package/src/webgpu/shims/ArrayCameraShim.js +74 -0
- package/src/webgpu/shims/EquirectCameraShim.js +37 -0
- package/src/webgpu/shims/PhysicalCameraShim.js +151 -0
- package/src/webgpu/upscale/FSRUpscaler.js +108 -0
package/build/index.umd.cjs
CHANGED
|
@@ -279,7 +279,20 @@
|
|
|
279
279
|
const attr = geometry.getAttribute( key );
|
|
280
280
|
if ( ! skip ) {
|
|
281
281
|
|
|
282
|
-
|
|
282
|
+
if ( key === 'color' && targetAttribute.itemSize !== attr.itemSize ) {
|
|
283
|
+
|
|
284
|
+
// make sure the color attribute is aligned with itemSize 3 to 4
|
|
285
|
+
for ( let index = offset, l = attr.count; index < l; index ++ ) {
|
|
286
|
+
|
|
287
|
+
attr.setXYZW( index, targetAttribute.getX( index ), targetAttribute.getY( index ), targetAttribute.getZ( index ), 1.0 );
|
|
288
|
+
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
} else {
|
|
292
|
+
|
|
293
|
+
copyAttributeContents( attr, targetAttribute, offset );
|
|
294
|
+
|
|
295
|
+
}
|
|
283
296
|
|
|
284
297
|
}
|
|
285
298
|
|
|
@@ -1317,6 +1330,7 @@
|
|
|
1317
1330
|
this._bvhWorker = null;
|
|
1318
1331
|
this._pendingGenerate = null;
|
|
1319
1332
|
this._buildAsync = false;
|
|
1333
|
+
this._materialUuids = null;
|
|
1320
1334
|
|
|
1321
1335
|
}
|
|
1322
1336
|
|
|
@@ -1398,12 +1412,29 @@
|
|
|
1398
1412
|
// generate the geometry
|
|
1399
1413
|
const result = staticGeometryGenerator.generate( geometry );
|
|
1400
1414
|
const materials = result.materials;
|
|
1415
|
+
let needsMaterialIndexUpdate = result.changeType !== NO_CHANGE || this._materialUuids === null || this._materialUuids.length !== length;
|
|
1416
|
+
if ( ! needsMaterialIndexUpdate ) {
|
|
1417
|
+
|
|
1418
|
+
for ( let i = 0, length = materials.length; i < length; i ++ ) {
|
|
1419
|
+
|
|
1420
|
+
const material = materials[ i ];
|
|
1421
|
+
if ( material.uuid !== this._materialUuids[ i ] ) {
|
|
1422
|
+
|
|
1423
|
+
needsMaterialIndexUpdate = true;
|
|
1424
|
+
break;
|
|
1425
|
+
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1401
1432
|
const textures = getTextures$1( materials );
|
|
1402
1433
|
const { lights, iesTextures } = getLights$1( objects );
|
|
1403
|
-
|
|
1404
|
-
if ( result.changeType !== NO_CHANGE ) {
|
|
1434
|
+
if ( needsMaterialIndexUpdate ) {
|
|
1405
1435
|
|
|
1406
1436
|
updateMaterialIndexAttribute( geometry, materials, materials );
|
|
1437
|
+
this._materialUuids = materials.map( material => material.uuid );
|
|
1407
1438
|
|
|
1408
1439
|
}
|
|
1409
1440
|
|
|
@@ -1447,6 +1478,7 @@
|
|
|
1447
1478
|
return {
|
|
1448
1479
|
bvhChanged: result.changeType !== NO_CHANGE,
|
|
1449
1480
|
bvh: this.bvh,
|
|
1481
|
+
needsMaterialIndexUpdate,
|
|
1450
1482
|
lights,
|
|
1451
1483
|
iesTextures,
|
|
1452
1484
|
geometry,
|
|
@@ -2216,6 +2248,12 @@
|
|
|
2216
2248
|
|
|
2217
2249
|
}
|
|
2218
2250
|
|
|
2251
|
+
getPixelWeight( r, g, b ) {
|
|
2252
|
+
|
|
2253
|
+
return colorToLuminance( r, g, b );
|
|
2254
|
+
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2219
2257
|
dispose() {
|
|
2220
2258
|
|
|
2221
2259
|
this.marginalWeights.dispose();
|
|
@@ -2256,10 +2294,9 @@
|
|
|
2256
2294
|
const g = three.DataUtils.fromHalfFloat( data[ 4 * i + 1 ] );
|
|
2257
2295
|
const b = three.DataUtils.fromHalfFloat( data[ 4 * i + 2 ] );
|
|
2258
2296
|
|
|
2259
|
-
// the probability of the pixel being selected in
|
|
2260
|
-
//
|
|
2261
|
-
|
|
2262
|
-
const weight = colorToLuminance( r, g, b );
|
|
2297
|
+
// the probability of the pixel being selected in its row is proportional
|
|
2298
|
+
// to its luminance relative to the other pixels.
|
|
2299
|
+
const weight = this.getPixelWeight( r, g, b, y, height );
|
|
2263
2300
|
cumulativeRowWeight += weight;
|
|
2264
2301
|
totalSumValue += weight;
|
|
2265
2302
|
|
|
@@ -2590,17 +2627,17 @@
|
|
|
2590
2627
|
let maxValue = 1.0;
|
|
2591
2628
|
switch ( fromArray.constructor ) {
|
|
2592
2629
|
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2630
|
+
case Uint8Array:
|
|
2631
|
+
case Uint16Array:
|
|
2632
|
+
case Uint32Array:
|
|
2633
|
+
maxValue = 2 ** bpe - 1;
|
|
2634
|
+
break;
|
|
2598
2635
|
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2636
|
+
case Int8Array:
|
|
2637
|
+
case Int16Array:
|
|
2638
|
+
case Int32Array:
|
|
2639
|
+
maxValue = 2 ** ( bpe - 1 ) - 1;
|
|
2640
|
+
break;
|
|
2604
2641
|
|
|
2605
2642
|
}
|
|
2606
2643
|
|
|
@@ -2851,20 +2888,16 @@
|
|
|
2851
2888
|
function getLights( scene ) {
|
|
2852
2889
|
|
|
2853
2890
|
const lights = [];
|
|
2854
|
-
scene.
|
|
2855
|
-
|
|
2856
|
-
if ( c.visible ) {
|
|
2891
|
+
scene.traverseVisible( c => {
|
|
2857
2892
|
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
lights.push( c );
|
|
2893
|
+
if (
|
|
2894
|
+
c.isRectAreaLight ||
|
|
2895
|
+
c.isSpotLight ||
|
|
2896
|
+
c.isPointLight ||
|
|
2897
|
+
c.isDirectionalLight
|
|
2898
|
+
) {
|
|
2866
2899
|
|
|
2867
|
-
|
|
2900
|
+
lights.push( c );
|
|
2868
2901
|
|
|
2869
2902
|
}
|
|
2870
2903
|
|
|
@@ -2874,7 +2907,7 @@
|
|
|
2874
2907
|
|
|
2875
2908
|
}
|
|
2876
2909
|
|
|
2877
|
-
const MATERIAL_PIXELS =
|
|
2910
|
+
const MATERIAL_PIXELS = 47;
|
|
2878
2911
|
const MATERIAL_STRIDE = MATERIAL_PIXELS * 4;
|
|
2879
2912
|
|
|
2880
2913
|
class MaterialFeatures {
|
|
@@ -3234,15 +3267,15 @@
|
|
|
3234
3267
|
|
|
3235
3268
|
switch ( m.side ) {
|
|
3236
3269
|
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3270
|
+
case three.FrontSide:
|
|
3271
|
+
floatArray[ index ++ ] = 1;
|
|
3272
|
+
break;
|
|
3273
|
+
case three.BackSide:
|
|
3274
|
+
floatArray[ index ++ ] = - 1;
|
|
3275
|
+
break;
|
|
3276
|
+
case three.DoubleSide:
|
|
3277
|
+
floatArray[ index ++ ] = 0;
|
|
3278
|
+
break;
|
|
3246
3279
|
|
|
3247
3280
|
}
|
|
3248
3281
|
|
|
@@ -3299,6 +3332,9 @@
|
|
|
3299
3332
|
// specularIntensityMap transform 43
|
|
3300
3333
|
index += writeTextureMatrixToArray( m, 'specularIntensityMap', floatArray, index );
|
|
3301
3334
|
|
|
3335
|
+
// alphaMap transform 45
|
|
3336
|
+
index += writeTextureMatrixToArray( m, 'alphaMap', floatArray, index );
|
|
3337
|
+
|
|
3302
3338
|
}
|
|
3303
3339
|
|
|
3304
3340
|
// check if the contents have changed
|
|
@@ -4112,12 +4148,12 @@
|
|
|
4112
4148
|
|
|
4113
4149
|
switch ( channels ) {
|
|
4114
4150
|
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4151
|
+
case 1:
|
|
4152
|
+
return three.RedFormat;
|
|
4153
|
+
case 2:
|
|
4154
|
+
return three.RGFormat;
|
|
4155
|
+
default:
|
|
4156
|
+
return three.RGBAFormat;
|
|
4121
4157
|
|
|
4122
4158
|
}
|
|
4123
4159
|
|
|
@@ -4378,6 +4414,7 @@
|
|
|
4378
4414
|
mat3 iridescenceThicknessMapTransform;
|
|
4379
4415
|
mat3 specularColorMapTransform;
|
|
4380
4416
|
mat3 specularIntensityMapTransform;
|
|
4417
|
+
mat3 alphaMapTransform;
|
|
4381
4418
|
|
|
4382
4419
|
};
|
|
4383
4420
|
|
|
@@ -4398,7 +4435,7 @@
|
|
|
4398
4435
|
|
|
4399
4436
|
Material readMaterialInfo( sampler2D tex, uint index ) {
|
|
4400
4437
|
|
|
4401
|
-
uint i = index *
|
|
4438
|
+
uint i = index * uint( MATERIAL_PIXELS );
|
|
4402
4439
|
|
|
4403
4440
|
vec4 s0 = texelFetch1D( tex, i + 0u );
|
|
4404
4441
|
vec4 s1 = texelFetch1D( tex, i + 1u );
|
|
@@ -4497,6 +4534,7 @@
|
|
|
4497
4534
|
m.iridescenceThicknessMapTransform = m.iridescenceThicknessMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 24u );
|
|
4498
4535
|
m.specularColorMapTransform = m.specularColorMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 26u );
|
|
4499
4536
|
m.specularIntensityMapTransform = m.specularIntensityMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 28u );
|
|
4537
|
+
m.alphaMapTransform = m.alphaMap == - 1 ? mat3( 1.0 ) : readTextureTransform( tex, firstTextureTransformIdx + 30u );
|
|
4500
4538
|
|
|
4501
4539
|
return m;
|
|
4502
4540
|
|
|
@@ -5677,7 +5715,6 @@
|
|
|
5677
5715
|
// See equation (1) in http://www.aconty.com/pdf/s2017_pbs_imageworks_sheen.pdf
|
|
5678
5716
|
vec3 color = surf.sheenColor;
|
|
5679
5717
|
color *= D * G / ( 4.0 * abs( cosThetaO * cosThetaI ) );
|
|
5680
|
-
color *= wi.z;
|
|
5681
5718
|
|
|
5682
5719
|
return color;
|
|
5683
5720
|
|
|
@@ -6263,7 +6300,7 @@
|
|
|
6263
6300
|
// returns whether the given material is a fog material or not
|
|
6264
6301
|
bool isMaterialFogVolume( sampler2D materials, uint materialIndex ) {
|
|
6265
6302
|
|
|
6266
|
-
uint i = materialIndex *
|
|
6303
|
+
uint i = materialIndex * uint( MATERIAL_PIXELS );
|
|
6267
6304
|
vec4 s14 = texelFetch1D( materials, i + 14u );
|
|
6268
6305
|
return bool( int( s14.b ) & 4 );
|
|
6269
6306
|
|
|
@@ -6493,7 +6530,8 @@ bool bvhIntersectFogVolumeHit(
|
|
|
6493
6530
|
// alphaMap
|
|
6494
6531
|
if ( material.alphaMap != - 1 ) {
|
|
6495
6532
|
|
|
6496
|
-
|
|
6533
|
+
vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
|
|
6534
|
+
albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
|
|
6497
6535
|
|
|
6498
6536
|
}
|
|
6499
6537
|
|
|
@@ -6635,7 +6673,7 @@ bool bvhIntersectFogVolumeHit(
|
|
|
6635
6673
|
vec3 shapeUVW= rand3( 1 );
|
|
6636
6674
|
int blades = physicalCamera.apertureBlades;
|
|
6637
6675
|
float anamorphicRatio = physicalCamera.anamorphicRatio;
|
|
6638
|
-
vec2 apertureSample =
|
|
6676
|
+
vec2 apertureSample = sampleAperture( blades, shapeUVW );
|
|
6639
6677
|
apertureSample *= physicalCamera.bokehSize * 0.5 * 1e-3;
|
|
6640
6678
|
|
|
6641
6679
|
// rotate the aperture shape
|
|
@@ -6805,7 +6843,8 @@ bool bvhIntersectFogVolumeHit(
|
|
|
6805
6843
|
// alphaMap
|
|
6806
6844
|
if ( material.alphaMap != - 1 ) {
|
|
6807
6845
|
|
|
6808
|
-
|
|
6846
|
+
vec3 uvPrime = material.alphaMapTransform * vec3( uv, 1 );
|
|
6847
|
+
albedo.a *= texture2D( textures, vec3( uvPrime.xy, material.alphaMap ) ).x;
|
|
6809
6848
|
|
|
6810
6849
|
}
|
|
6811
6850
|
|
|
@@ -7220,6 +7259,7 @@ bool bvhIntersectFogVolumeHit(
|
|
|
7220
7259
|
ATTR_TANGENT: 1,
|
|
7221
7260
|
ATTR_UV: 2,
|
|
7222
7261
|
ATTR_COLOR: 3,
|
|
7262
|
+
MATERIAL_PIXELS: MATERIAL_PIXELS,
|
|
7223
7263
|
},
|
|
7224
7264
|
|
|
7225
7265
|
uniforms: {
|
|
@@ -8155,8 +8195,8 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8155
8195
|
constructor( width = 512, height = 512 ) {
|
|
8156
8196
|
|
|
8157
8197
|
super(
|
|
8158
|
-
new
|
|
8159
|
-
width, height, three.RGBAFormat, three.
|
|
8198
|
+
new Uint16Array( width * height * 4 ),
|
|
8199
|
+
width, height, three.RGBAFormat, three.HalfFloatType, three.EquirectangularReflectionMapping,
|
|
8160
8200
|
three.RepeatWrapping, three.ClampToEdgeWrapping, three.LinearFilter, three.LinearFilter,
|
|
8161
8201
|
);
|
|
8162
8202
|
|
|
@@ -8188,10 +8228,10 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8188
8228
|
|
|
8189
8229
|
const i = y * width + x;
|
|
8190
8230
|
const i4 = 4 * i;
|
|
8191
|
-
data[ i4 + 0 ] = ( _color.r );
|
|
8192
|
-
data[ i4 + 1 ] = ( _color.g );
|
|
8193
|
-
data[ i4 + 2 ] = ( _color.b );
|
|
8194
|
-
data[ i4 + 3 ] = ( 1.0 );
|
|
8231
|
+
data[ i4 + 0 ] = three.DataUtils.toHalfFloat( _color.r );
|
|
8232
|
+
data[ i4 + 1 ] = three.DataUtils.toHalfFloat( _color.g );
|
|
8233
|
+
data[ i4 + 2 ] = three.DataUtils.toHalfFloat( _color.b );
|
|
8234
|
+
data[ i4 + 3 ] = three.DataUtils.toHalfFloat( 1.0 );
|
|
8195
8235
|
|
|
8196
8236
|
}
|
|
8197
8237
|
|
|
@@ -8592,6 +8632,8 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8592
8632
|
|
|
8593
8633
|
constructor( renderer ) {
|
|
8594
8634
|
|
|
8635
|
+
console.warn( 'WebGLPathTracer: This class has been deprecated and will be removed in a future release. Use "WebGPUPathTracer" instead.' );
|
|
8636
|
+
|
|
8595
8637
|
// members
|
|
8596
8638
|
this._renderer = renderer;
|
|
8597
8639
|
this._generator = new PathTracingSceneGenerator();
|
|
@@ -8796,7 +8838,7 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8796
8838
|
}
|
|
8797
8839
|
|
|
8798
8840
|
// update scene environment
|
|
8799
|
-
material.environmentIntensity = scene.environmentIntensity ?? 1;
|
|
8841
|
+
material.environmentIntensity = scene.environment !== null ? ( scene.environmentIntensity ?? 1 ) : 0;
|
|
8800
8842
|
material.environmentRotation.makeRotationFromEuler( scene.environmentRotation ).invert();
|
|
8801
8843
|
if ( this._previousEnvironment !== scene.environment ) {
|
|
8802
8844
|
|
|
@@ -8816,10 +8858,6 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8816
8858
|
|
|
8817
8859
|
}
|
|
8818
8860
|
|
|
8819
|
-
} else {
|
|
8820
|
-
|
|
8821
|
-
material.environmentIntensity = 0;
|
|
8822
|
-
|
|
8823
8861
|
}
|
|
8824
8862
|
|
|
8825
8863
|
}
|
|
@@ -8837,6 +8875,7 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8837
8875
|
geometry,
|
|
8838
8876
|
bvh,
|
|
8839
8877
|
bvhChanged,
|
|
8878
|
+
needsMaterialIndexUpdate,
|
|
8840
8879
|
} = results;
|
|
8841
8880
|
|
|
8842
8881
|
this._materials = materials;
|
|
@@ -8854,6 +8893,10 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8854
8893
|
geometry.attributes.color,
|
|
8855
8894
|
);
|
|
8856
8895
|
|
|
8896
|
+
}
|
|
8897
|
+
|
|
8898
|
+
if ( needsMaterialIndexUpdate ) {
|
|
8899
|
+
|
|
8857
8900
|
material.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
|
|
8858
8901
|
|
|
8859
8902
|
}
|
|
@@ -8984,8 +9027,8 @@ bool bvhIntersectFogVolumeHit(
|
|
|
8984
9027
|
|
|
8985
9028
|
dispose() {
|
|
8986
9029
|
|
|
8987
|
-
this.
|
|
8988
|
-
this.
|
|
9030
|
+
this._quad.dispose();
|
|
9031
|
+
this._quad.material.dispose();
|
|
8989
9032
|
this._pathTracer.dispose();
|
|
8990
9033
|
|
|
8991
9034
|
}
|
|
@@ -9013,6 +9056,12 @@ bool bvhIntersectFogVolumeHit(
|
|
|
9013
9056
|
|
|
9014
9057
|
}
|
|
9015
9058
|
|
|
9059
|
+
getRenderTime() {
|
|
9060
|
+
|
|
9061
|
+
return this._clock.getElapsedTime() * 1e3;
|
|
9062
|
+
|
|
9063
|
+
}
|
|
9064
|
+
|
|
9016
9065
|
}
|
|
9017
9066
|
|
|
9018
9067
|
class EquirectCamera extends three.Camera {
|
|
@@ -9027,6 +9076,8 @@ bool bvhIntersectFogVolumeHit(
|
|
|
9027
9076
|
|
|
9028
9077
|
}
|
|
9029
9078
|
|
|
9079
|
+
// TODO: this should extend IESSpotLight, but the class is only exported from "three/webgpu" and
|
|
9080
|
+
// the node library resolves light nodes by exact constructor so a subclass would not rasterize
|
|
9030
9081
|
class PhysicalSpotLight extends three.SpotLight {
|
|
9031
9082
|
|
|
9032
9083
|
constructor( ...args ) {
|
|
@@ -9357,8 +9408,211 @@ bool bvhIntersectFogVolumeHit(
|
|
|
9357
9408
|
|
|
9358
9409
|
}
|
|
9359
9410
|
|
|
9411
|
+
class AmbientOcclusionMaterial extends MaterialBase {
|
|
9412
|
+
|
|
9413
|
+
get normalMap() {
|
|
9414
|
+
|
|
9415
|
+
return this.uniforms.normalMap.value;
|
|
9416
|
+
|
|
9417
|
+
}
|
|
9418
|
+
|
|
9419
|
+
set normalMap( v ) {
|
|
9420
|
+
|
|
9421
|
+
this.uniforms.normalMap.value = v;
|
|
9422
|
+
this.setDefine( 'USE_NORMALMAP', v ? null : '' );
|
|
9423
|
+
|
|
9424
|
+
}
|
|
9425
|
+
|
|
9426
|
+
get normalMapType() {
|
|
9427
|
+
|
|
9428
|
+
return three.TangentSpaceNormalMap;
|
|
9429
|
+
|
|
9430
|
+
}
|
|
9431
|
+
|
|
9432
|
+
set normalMapType( v ) {
|
|
9433
|
+
|
|
9434
|
+
if ( v !== three.TangentSpaceNormalMap ) {
|
|
9435
|
+
|
|
9436
|
+
throw new Error( 'AmbientOcclusionMaterial: Only tangent space normal map are supported' );
|
|
9437
|
+
|
|
9438
|
+
}
|
|
9439
|
+
|
|
9440
|
+
}
|
|
9441
|
+
|
|
9442
|
+
constructor( parameters ) {
|
|
9443
|
+
|
|
9444
|
+
super( {
|
|
9445
|
+
|
|
9446
|
+
defines: {
|
|
9447
|
+
SAMPLES: 10,
|
|
9448
|
+
MATERIAL_PIXELS: MATERIAL_PIXELS,
|
|
9449
|
+
},
|
|
9450
|
+
|
|
9451
|
+
uniforms: {
|
|
9452
|
+
bvh: { value: new threeMeshBvh.MeshBVHUniformStruct() },
|
|
9453
|
+
radius: { value: 1.0 },
|
|
9454
|
+
seed: { value: 0 },
|
|
9455
|
+
|
|
9456
|
+
normalMap: { value: null },
|
|
9457
|
+
normalScale: { value: new three.Vector2( 1, 1 ) },
|
|
9458
|
+
},
|
|
9459
|
+
|
|
9460
|
+
vertexShader: /* glsl */`
|
|
9461
|
+
|
|
9462
|
+
varying vec3 vNorm;
|
|
9463
|
+
varying vec3 vPos;
|
|
9464
|
+
|
|
9465
|
+
#if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
|
|
9466
|
+
|
|
9467
|
+
varying vec2 vUv;
|
|
9468
|
+
varying vec4 vTan;
|
|
9469
|
+
|
|
9470
|
+
#endif
|
|
9471
|
+
|
|
9472
|
+
void main() {
|
|
9473
|
+
|
|
9474
|
+
vec4 mvPosition = vec4( position, 1.0 );
|
|
9475
|
+
mvPosition = modelViewMatrix * mvPosition;
|
|
9476
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
9477
|
+
|
|
9478
|
+
mat3 modelNormalMatrix = transpose( inverse( mat3( modelMatrix ) ) );
|
|
9479
|
+
vNorm = normalize( modelNormalMatrix * normal );
|
|
9480
|
+
vPos = ( modelMatrix * vec4( position, 1.0 ) ).xyz;
|
|
9481
|
+
|
|
9482
|
+
#if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
|
|
9483
|
+
|
|
9484
|
+
vUv = uv;
|
|
9485
|
+
vTan = tangent;
|
|
9486
|
+
|
|
9487
|
+
#endif
|
|
9488
|
+
|
|
9489
|
+
}
|
|
9490
|
+
|
|
9491
|
+
`,
|
|
9492
|
+
|
|
9493
|
+
fragmentShader: /* glsl */`
|
|
9494
|
+
#define RAY_OFFSET 1e-4
|
|
9495
|
+
|
|
9496
|
+
precision highp isampler2D;
|
|
9497
|
+
precision highp usampler2D;
|
|
9498
|
+
precision highp sampler2DArray;
|
|
9499
|
+
#include <common>
|
|
9500
|
+
#include <cube_uv_reflection_fragment>
|
|
9501
|
+
|
|
9502
|
+
// bvh
|
|
9503
|
+
${ threeMeshBvh.BVHShaderGLSL.common_functions }
|
|
9504
|
+
${ threeMeshBvh.BVHShaderGLSL.bvh_struct_definitions }
|
|
9505
|
+
${ threeMeshBvh.BVHShaderGLSL.bvh_ray_functions }
|
|
9506
|
+
|
|
9507
|
+
// uniform structs
|
|
9508
|
+
${ material_struct }
|
|
9509
|
+
|
|
9510
|
+
// rand
|
|
9511
|
+
${ pcg_functions }
|
|
9512
|
+
|
|
9513
|
+
// common
|
|
9514
|
+
${ shape_sampling_functions }
|
|
9515
|
+
|
|
9516
|
+
uniform BVH bvh;
|
|
9517
|
+
uniform int seed;
|
|
9518
|
+
uniform float radius;
|
|
9519
|
+
|
|
9520
|
+
varying vec3 vNorm;
|
|
9521
|
+
varying vec3 vPos;
|
|
9522
|
+
|
|
9523
|
+
#if defined(USE_NORMALMAP) && defined(USE_TANGENT)
|
|
9524
|
+
|
|
9525
|
+
uniform sampler2D normalMap;
|
|
9526
|
+
uniform vec2 normalScale;
|
|
9527
|
+
varying vec2 vUv;
|
|
9528
|
+
varying vec4 vTan;
|
|
9529
|
+
|
|
9530
|
+
#endif
|
|
9531
|
+
|
|
9532
|
+
void main() {
|
|
9533
|
+
|
|
9534
|
+
rng_initialize( gl_FragCoord.xy, seed );
|
|
9535
|
+
|
|
9536
|
+
// compute the flat face surface normal
|
|
9537
|
+
vec3 fdx = vec3( dFdx( vPos.x ), dFdx( vPos.y ), dFdx( vPos.z ) );
|
|
9538
|
+
vec3 fdy = vec3( dFdy( vPos.x ), dFdy( vPos.y ), dFdy( vPos.z ) );
|
|
9539
|
+
vec3 faceNormal = normalize( cross( fdx, fdy ) );
|
|
9540
|
+
|
|
9541
|
+
// find the max component to scale the offset to account for floating point error
|
|
9542
|
+
vec3 absPoint = abs( vPos );
|
|
9543
|
+
float maxPoint = max( absPoint.x, max( absPoint.y, absPoint.z ) );
|
|
9544
|
+
vec3 normal = vNorm;
|
|
9545
|
+
|
|
9546
|
+
#if defined( USE_NORMALMAP ) && defined( USE_TANGENT )
|
|
9547
|
+
|
|
9548
|
+
// some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
|
|
9549
|
+
// resulting in NaNs and slow path tracing.
|
|
9550
|
+
if ( length( vTan.xyz ) > 0.0 ) {
|
|
9551
|
+
|
|
9552
|
+
vec2 uv = vUv;
|
|
9553
|
+
vec3 tangent = normalize( vTan.xyz );
|
|
9554
|
+
vec3 bitangent = normalize( cross( normal, tangent ) * vTan.w );
|
|
9555
|
+
mat3 vTBN = mat3( tangent, bitangent, normal );
|
|
9556
|
+
|
|
9557
|
+
vec3 texNormal = texture2D( normalMap, uv ).xyz * 2.0 - 1.0;
|
|
9558
|
+
texNormal.xy *= normalScale;
|
|
9559
|
+
normal = vTBN * texNormal;
|
|
9560
|
+
|
|
9561
|
+
}
|
|
9562
|
+
|
|
9563
|
+
#endif
|
|
9564
|
+
|
|
9565
|
+
normal *= gl_FrontFacing ? 1.0 : - 1.0;
|
|
9566
|
+
|
|
9567
|
+
vec3 rayOrigin = vPos + faceNormal * ( maxPoint + 1.0 ) * RAY_OFFSET;
|
|
9568
|
+
float accumulated = 0.0;
|
|
9569
|
+
for ( int i = 0; i < SAMPLES; i ++ ) {
|
|
9570
|
+
|
|
9571
|
+
// sample the cosine weighted hemisphere and discard the sample if it's below
|
|
9572
|
+
// the geometric surface
|
|
9573
|
+
vec3 rayDirection = sampleHemisphere( normalize( normal ), pcgRand4().xy );
|
|
9574
|
+
|
|
9575
|
+
// check if we hit the mesh and its within the specified radius
|
|
9576
|
+
float side = 1.0;
|
|
9577
|
+
float dist = 0.0;
|
|
9578
|
+
vec3 barycoord = vec3( 0.0 );
|
|
9579
|
+
vec3 outNormal = vec3( 0.0 );
|
|
9580
|
+
uvec4 faceIndices = uvec4( 0u );
|
|
9581
|
+
|
|
9582
|
+
// if the ray is above the geometry surface, and it doesn't hit another surface within the specified radius then
|
|
9583
|
+
// we consider it lit
|
|
9584
|
+
if (
|
|
9585
|
+
dot( rayDirection, faceNormal ) > 0.0 &&
|
|
9586
|
+
(
|
|
9587
|
+
! bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, outNormal, barycoord, side, dist ) ||
|
|
9588
|
+
dist >= radius
|
|
9589
|
+
)
|
|
9590
|
+
) {
|
|
9591
|
+
|
|
9592
|
+
accumulated += 1.0;
|
|
9593
|
+
|
|
9594
|
+
}
|
|
9595
|
+
|
|
9596
|
+
}
|
|
9597
|
+
|
|
9598
|
+
gl_FragColor.rgb = vec3( accumulated / float( SAMPLES ) );
|
|
9599
|
+
gl_FragColor.a = 1.0;
|
|
9600
|
+
|
|
9601
|
+
}
|
|
9602
|
+
|
|
9603
|
+
`
|
|
9604
|
+
|
|
9605
|
+
} );
|
|
9606
|
+
|
|
9607
|
+
this.setValues( parameters );
|
|
9608
|
+
|
|
9609
|
+
}
|
|
9610
|
+
|
|
9611
|
+
}
|
|
9612
|
+
|
|
9360
9613
|
// core
|
|
9361
9614
|
|
|
9615
|
+
exports.AmbientOcclusionMaterial = AmbientOcclusionMaterial;
|
|
9362
9616
|
exports.BlurredEnvMapGenerator = BlurredEnvMapGenerator;
|
|
9363
9617
|
exports.DenoiseMaterial = DenoiseMaterial;
|
|
9364
9618
|
exports.DynamicPathTracingSceneGenerator = DynamicPathTracingSceneGenerator;
|