three-gpu-pathtracer 0.0.14 → 0.0.16
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/LICENSE +21 -21
- package/README.md +1004 -981
- package/build/index.module.js +7413 -6902
- package/build/index.module.js.map +1 -1
- package/build/index.umd.cjs +7446 -6933
- package/build/index.umd.cjs.map +1 -1
- package/package.json +73 -73
- package/src/core/DynamicPathTracingSceneGenerator.js +119 -119
- package/src/core/MaterialReducer.js +256 -256
- package/src/core/PathTracingRenderer.js +346 -346
- package/src/core/PathTracingSceneGenerator.js +69 -69
- package/src/core/QuiltPathTracingRenderer.js +223 -223
- package/src/detectors/CompatibilityDetector.js +38 -0
- package/src/detectors/MaterialCompileDetector.js +50 -0
- package/src/detectors/PrecisionDetector.js +85 -0
- package/src/detectors/PrecisionMaterial.js +160 -0
- package/src/index.js +40 -36
- package/src/materials/MaterialBase.js +56 -56
- package/src/materials/debug/GraphMaterial.js +243 -243
- package/src/materials/fullscreen/AlphaDisplayMaterial.js +50 -48
- package/src/materials/fullscreen/BlendMaterial.js +67 -67
- package/src/materials/fullscreen/DenoiseMaterial.js +142 -142
- package/src/materials/fullscreen/GradientMapMaterial.js +82 -0
- package/src/materials/pathtracing/LambertPathTracingMaterial.js +296 -296
- package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +118 -196
- package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +177 -179
- package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +84 -81
- package/src/materials/pathtracing/glsl/directLightContribution.glsl.js +93 -0
- package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +323 -317
- package/src/materials/pathtracing/glsl/renderStructs.glsl.js +50 -0
- package/src/materials/pathtracing/glsl/traceScene.glsl.js +52 -54
- package/src/materials/surface/AmbientOcclusionMaterial.js +207 -207
- package/src/materials/surface/FogVolumeMaterial.js +23 -23
- package/src/objects/EquirectCamera.js +13 -13
- package/src/objects/PhysicalCamera.js +42 -28
- package/src/objects/PhysicalSpotLight.js +25 -14
- package/src/objects/ShapedAreaLight.js +22 -12
- package/src/shader/bsdf/bsdfSampling.glsl.js +499 -490
- package/src/shader/bsdf/fog.glsl.js +22 -23
- package/src/shader/bsdf/ggx.glsl.js +102 -102
- package/src/shader/bsdf/iridescence.glsl.js +135 -135
- package/src/shader/bsdf/sheen.glsl.js +98 -98
- package/src/shader/common/arraySamplerTexelFetch.glsl.js +25 -25
- package/src/shader/common/bvhAnyHit.glsl.js +76 -76
- package/src/shader/common/fresnel.glsl.js +98 -98
- package/src/shader/common/intersectShapes.glsl.js +62 -62
- package/src/shader/common/math.glsl.js +81 -81
- package/src/shader/common/utils.glsl.js +116 -116
- package/src/shader/rand/pcg.glsl.js +57 -57
- package/src/shader/rand/sobol.glsl.js +256 -256
- package/src/shader/sampling/equirectSampling.glsl.js +62 -62
- package/src/shader/sampling/lightSampling.glsl.js +223 -223
- package/src/shader/sampling/shapeSampling.glsl.js +86 -86
- package/src/shader/structs/cameraStruct.glsl.js +13 -13
- package/src/shader/structs/equirectStruct.glsl.js +13 -14
- package/src/shader/structs/fogMaterialBvh.glsl.js +62 -62
- package/src/shader/structs/lightsStruct.glsl.js +78 -78
- package/src/shader/structs/materialStruct.glsl.js +207 -207
- package/src/textures/GradientEquirectTexture.js +35 -35
- package/src/textures/ProceduralEquirectTexture.js +75 -75
- package/src/uniforms/AttributesTextureArray.js +35 -35
- package/src/uniforms/EquirectHdrInfoUniform.js +269 -277
- package/src/uniforms/FloatAttributeTextureArray.js +169 -169
- package/src/uniforms/IESProfilesTexture.js +100 -100
- package/src/uniforms/LightsInfoUniformStruct.js +212 -212
- package/src/uniforms/MaterialsTexture.js +503 -503
- package/src/uniforms/PhysicalCameraUniform.js +36 -36
- package/src/uniforms/RenderTarget2DArray.js +97 -97
- package/src/uniforms/utils.js +30 -30
- package/src/utils/BlurredEnvMapGenerator.js +116 -116
- package/src/utils/GeometryPreparationUtils.js +214 -214
- package/src/utils/IESLoader.js +325 -325
- package/src/utils/SobolNumberMapGenerator.js +80 -80
- package/src/utils/UVUnwrapper.js +101 -101
- package/src/utils/macroify.js +9 -9
- package/src/workers/PathTracingSceneWorker.js +42 -42
|
@@ -31,7 +31,7 @@ import { lightSamplingGLSL } from '../../shader/sampling/lightSampling.glsl.js';
|
|
|
31
31
|
import { shapeSamplingGLSL } from '../../shader/sampling/shapeSampling.glsl.js';
|
|
32
32
|
|
|
33
33
|
// common glsl
|
|
34
|
-
import { intersectShapesGLSL } from '../../shader/common/intersectShapes.glsl';
|
|
34
|
+
import { intersectShapesGLSL } from '../../shader/common/intersectShapes.glsl.js';
|
|
35
35
|
import { mathGLSL } from '../../shader/common/math.glsl.js';
|
|
36
36
|
import { utilsGLSL } from '../../shader/common/utils.glsl.js';
|
|
37
37
|
import { fresnelGLSL } from '../../shader/common/fresnel.glsl.js';
|
|
@@ -42,10 +42,12 @@ import { pcgGLSL } from '../../shader/rand/pcg.glsl.js';
|
|
|
42
42
|
import { sobolCommonGLSL, sobolSamplingGLSL } from '../../shader/rand/sobol.glsl.js';
|
|
43
43
|
|
|
44
44
|
// path tracer utils
|
|
45
|
+
import { renderStructsGLSL } from './glsl/renderStructs.glsl.js';
|
|
45
46
|
import { cameraUtilsGLSL } from './glsl/cameraUtils.glsl.js';
|
|
46
47
|
import { attenuateHitGLSL } from './glsl/attenuateHit.glsl.js';
|
|
47
48
|
import { traceSceneGLSL } from './glsl/traceScene.glsl.js';
|
|
48
49
|
import { getSurfaceRecordGLSL } from './glsl/getSurfaceRecord.glsl.js';
|
|
50
|
+
import { directLightContributionGLSL } from './glsl/directLightContribution.glsl.js';
|
|
49
51
|
|
|
50
52
|
export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
51
53
|
|
|
@@ -75,6 +77,8 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
75
77
|
// 2 = Equirectangular
|
|
76
78
|
CAMERA_TYPE: 0,
|
|
77
79
|
|
|
80
|
+
DEBUG_MODE: 0,
|
|
81
|
+
|
|
78
82
|
ATTR_NORMAL: 0,
|
|
79
83
|
ATTR_TANGENT: 1,
|
|
80
84
|
ATTR_UV: 2,
|
|
@@ -212,9 +216,10 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
212
216
|
|
|
213
217
|
varying vec2 vUv;
|
|
214
218
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
219
|
+
// globals
|
|
220
|
+
mat3 envRotation3x3;
|
|
221
|
+
mat3 invEnvRotation3x3;
|
|
222
|
+
float lightsDenom;
|
|
218
223
|
|
|
219
224
|
float applyFilteredGlossy( float roughness, float accumulatedRoughness ) {
|
|
220
225
|
|
|
@@ -244,6 +249,11 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
244
249
|
|
|
245
250
|
}
|
|
246
251
|
|
|
252
|
+
${ renderStructsGLSL }
|
|
253
|
+
${ cameraUtilsGLSL }
|
|
254
|
+
${ traceSceneGLSL }
|
|
255
|
+
${ attenuateHitGLSL }
|
|
256
|
+
${ directLightContributionGLSL }
|
|
247
257
|
${ getSurfaceRecordGLSL }
|
|
248
258
|
|
|
249
259
|
void main() {
|
|
@@ -254,85 +264,73 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
254
264
|
sobolPathIndex = uint( seed );
|
|
255
265
|
|
|
256
266
|
// get camera ray
|
|
257
|
-
|
|
258
|
-
getCameraRay( rayDirection, rayOrigin );
|
|
267
|
+
Ray ray = getCameraRay();
|
|
259
268
|
|
|
260
269
|
// inverse environment rotation
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
270
|
+
envRotation3x3 = mat3( environmentRotation );
|
|
271
|
+
invEnvRotation3x3 = inverse( envRotation3x3 );
|
|
272
|
+
lightsDenom = environmentIntensity == 0.0 && lights.count != 0u ? float( lights.count ) : float( lights.count + 1u );
|
|
264
273
|
|
|
265
274
|
// final color
|
|
266
|
-
gl_FragColor = vec4( 0
|
|
267
|
-
gl_FragColor.a = 1.0;
|
|
275
|
+
gl_FragColor = vec4( 0, 0, 0, 1 );
|
|
268
276
|
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
float side = 1.0;
|
|
274
|
-
float dist = 0.0;
|
|
277
|
+
// surface results
|
|
278
|
+
SurfaceHit surfaceHit;
|
|
279
|
+
LightRecord lightRec;
|
|
280
|
+
ScatterRecord scatterRec;
|
|
275
281
|
|
|
276
282
|
// path tracing state
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
bool isShadowRay = false;
|
|
280
|
-
int transmissiveTraversals = transmissiveBounces;
|
|
281
|
-
vec3 throughputColor = vec3( 1.0 );
|
|
282
|
-
ScatterRecord sampleRec;
|
|
283
|
-
int i;
|
|
284
|
-
|
|
285
|
-
Material fogMaterial;
|
|
283
|
+
RenderState state = initRenderState();
|
|
284
|
+
state.transmissiveTraversals = transmissiveBounces;
|
|
286
285
|
#if FEATURE_FOG
|
|
287
286
|
|
|
288
|
-
fogMaterial.fogVolume = bvhIntersectFogVolumeHit(
|
|
289
|
-
bvh,
|
|
287
|
+
state.fogMaterial.fogVolume = bvhIntersectFogVolumeHit(
|
|
288
|
+
bvh, ray.origin, - ray.direction,
|
|
290
289
|
materialIndexAttribute, materials,
|
|
291
|
-
fogMaterial
|
|
290
|
+
state.fogMaterial
|
|
292
291
|
);
|
|
293
292
|
|
|
294
293
|
#endif
|
|
295
294
|
|
|
296
|
-
for ( i = 0; i < bounces; i ++ ) {
|
|
295
|
+
for ( int i = 0; i < bounces; i ++ ) {
|
|
297
296
|
|
|
298
297
|
sobolBounceIndex ++;
|
|
299
298
|
|
|
300
|
-
|
|
299
|
+
state.depth ++;
|
|
300
|
+
state.traversals = bounces - i;
|
|
301
|
+
state.firstRay = i == 0 && state.transmissiveTraversals == transmissiveBounces;
|
|
301
302
|
|
|
302
|
-
LightSampleRecord lightSampleRec;
|
|
303
303
|
int hitType = traceScene(
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
faceIndices, faceNormal, barycoord, side, dist,
|
|
307
|
-
lightSampleRec
|
|
304
|
+
ray, bvh, lights, state.fogMaterial,
|
|
305
|
+
surfaceHit, lightRec
|
|
308
306
|
);
|
|
309
307
|
|
|
310
308
|
if ( hitType == LIGHT_HIT ) {
|
|
311
309
|
|
|
312
|
-
if ( firstRay || transmissiveRay ) {
|
|
310
|
+
if ( state.firstRay || state.transmissiveRay ) {
|
|
313
311
|
|
|
314
|
-
gl_FragColor.rgb +=
|
|
312
|
+
gl_FragColor.rgb += lightRec.emission * state.throughputColor;
|
|
315
313
|
|
|
316
314
|
} else {
|
|
317
315
|
|
|
318
316
|
#if FEATURE_MIS
|
|
319
317
|
|
|
320
318
|
// NOTE: we skip MIS for punctual lights since they are not supported in forward PT case
|
|
321
|
-
if (
|
|
319
|
+
if ( lightRec.type == SPOT_LIGHT_TYPE || lightRec.type == DIR_LIGHT_TYPE || lightRec.type == POINT_LIGHT_TYPE ) {
|
|
322
320
|
|
|
323
|
-
gl_FragColor.rgb +=
|
|
321
|
+
gl_FragColor.rgb += lightRec.emission * state.throughputColor;
|
|
324
322
|
|
|
325
323
|
} else {
|
|
326
324
|
|
|
327
325
|
// weight the contribution
|
|
328
|
-
float misWeight = misHeuristic(
|
|
329
|
-
gl_FragColor.rgb +=
|
|
326
|
+
float misWeight = misHeuristic( scatterRec.pdf, lightRec.pdf / lightsDenom );
|
|
327
|
+
gl_FragColor.rgb += lightRec.emission * state.throughputColor * misWeight;
|
|
330
328
|
|
|
331
329
|
}
|
|
332
330
|
|
|
333
331
|
#else
|
|
334
332
|
|
|
335
|
-
gl_FragColor.rgb +=
|
|
333
|
+
gl_FragColor.rgb += lightRec.emission * state.throughputColor;
|
|
336
334
|
|
|
337
335
|
#endif
|
|
338
336
|
|
|
@@ -341,9 +339,9 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
341
339
|
|
|
342
340
|
} else if ( hitType == NO_HIT ) {
|
|
343
341
|
|
|
344
|
-
if ( firstRay || transmissiveRay ) {
|
|
342
|
+
if ( state.firstRay || state.transmissiveRay ) {
|
|
345
343
|
|
|
346
|
-
gl_FragColor.rgb += sampleBackground( envRotation3x3 *
|
|
344
|
+
gl_FragColor.rgb += sampleBackground( envRotation3x3 * ray.direction, sobol2( 2 ) ) * state.throughputColor;
|
|
347
345
|
gl_FragColor.a = backgroundAlpha;
|
|
348
346
|
|
|
349
347
|
} else {
|
|
@@ -352,19 +350,19 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
352
350
|
|
|
353
351
|
// get the PDF of the hit envmap point
|
|
354
352
|
vec3 envColor;
|
|
355
|
-
float envPdf = sampleEquirect( envMapInfo, envRotation3x3 *
|
|
353
|
+
float envPdf = sampleEquirect( envMapInfo, envRotation3x3 * ray.direction, envColor );
|
|
356
354
|
envPdf /= lightsDenom;
|
|
357
355
|
|
|
358
356
|
// and weight the contribution
|
|
359
|
-
float misWeight = misHeuristic(
|
|
360
|
-
gl_FragColor.rgb += environmentIntensity * envColor * throughputColor * misWeight;
|
|
357
|
+
float misWeight = misHeuristic( scatterRec.pdf, envPdf );
|
|
358
|
+
gl_FragColor.rgb += environmentIntensity * envColor * state.throughputColor * misWeight;
|
|
361
359
|
|
|
362
360
|
#else
|
|
363
361
|
|
|
364
362
|
gl_FragColor.rgb +=
|
|
365
363
|
environmentIntensity *
|
|
366
|
-
sampleEquirectColor( envMapInfo.map, envRotation3x3 *
|
|
367
|
-
throughputColor;
|
|
364
|
+
sampleEquirectColor( envMapInfo.map, envRotation3x3 * ray.direction ) *
|
|
365
|
+
state.throughputColor;
|
|
368
366
|
|
|
369
367
|
#endif
|
|
370
368
|
|
|
@@ -373,32 +371,33 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
373
371
|
|
|
374
372
|
}
|
|
375
373
|
|
|
376
|
-
uint materialIndex = uTexelFetch1D( materialIndexAttribute, faceIndices.x ).r;
|
|
374
|
+
uint materialIndex = uTexelFetch1D( materialIndexAttribute, surfaceHit.faceIndices.x ).r;
|
|
377
375
|
Material material = readMaterialInfo( materials, materialIndex );
|
|
378
376
|
|
|
379
377
|
#if FEATURE_FOG
|
|
380
378
|
|
|
381
379
|
if ( hitType == FOG_HIT ) {
|
|
382
380
|
|
|
383
|
-
material = fogMaterial;
|
|
384
|
-
accumulatedRoughness += 0.2;
|
|
381
|
+
material = state.fogMaterial;
|
|
382
|
+
state.accumulatedRoughness += 0.2;
|
|
385
383
|
|
|
386
384
|
} else if ( material.fogVolume ) {
|
|
387
385
|
|
|
388
|
-
fogMaterial = material;
|
|
389
|
-
fogMaterial.fogVolume = side == 1.0;
|
|
386
|
+
state.fogMaterial = material;
|
|
387
|
+
state.fogMaterial.fogVolume = surfaceHit.side == 1.0;
|
|
390
388
|
|
|
391
|
-
|
|
389
|
+
ray.origin = stepRayOrigin( ray.origin, ray.direction, - surfaceHit.faceNormal, surfaceHit.dist );
|
|
392
390
|
|
|
393
|
-
i -= sign( transmissiveTraversals );
|
|
394
|
-
transmissiveTraversals -= sign( transmissiveTraversals );
|
|
391
|
+
i -= sign( state.transmissiveTraversals );
|
|
392
|
+
state.transmissiveTraversals -= sign( state.transmissiveTraversals );
|
|
395
393
|
continue;
|
|
396
394
|
|
|
397
395
|
}
|
|
398
396
|
|
|
399
397
|
#endif
|
|
400
398
|
|
|
401
|
-
if
|
|
399
|
+
// early out if this is a matte material
|
|
400
|
+
if ( material.matte && state.firstRay ) {
|
|
402
401
|
|
|
403
402
|
gl_FragColor = vec4( 0.0 );
|
|
404
403
|
break;
|
|
@@ -407,9 +406,9 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
407
406
|
|
|
408
407
|
// if we've determined that this is a shadow ray and we've hit an item with no shadow casting
|
|
409
408
|
// then skip it
|
|
410
|
-
if ( ! material.castShadow && isShadowRay ) {
|
|
409
|
+
if ( ! material.castShadow && state.isShadowRay ) {
|
|
411
410
|
|
|
412
|
-
|
|
411
|
+
ray.origin = stepRayOrigin( ray.origin, ray.direction, - surfaceHit.faceNormal, surfaceHit.dist );
|
|
413
412
|
continue;
|
|
414
413
|
|
|
415
414
|
}
|
|
@@ -417,164 +416,77 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
417
416
|
SurfaceRecord surf;
|
|
418
417
|
if (
|
|
419
418
|
getSurfaceRecord(
|
|
420
|
-
material,
|
|
421
|
-
faceNormal, accumulatedRoughness,
|
|
419
|
+
material, surfaceHit, attributesArray, state.accumulatedRoughness,
|
|
422
420
|
surf
|
|
423
421
|
) == SKIP_SURFACE
|
|
424
422
|
) {
|
|
425
423
|
|
|
426
424
|
// only allow a limited number of transparency discards otherwise we could
|
|
427
425
|
// crash the context with too long a loop.
|
|
428
|
-
i -= sign( transmissiveTraversals );
|
|
429
|
-
transmissiveTraversals -= sign( transmissiveTraversals );
|
|
426
|
+
i -= sign( state.transmissiveTraversals );
|
|
427
|
+
state.transmissiveTraversals -= sign( state.transmissiveTraversals );
|
|
430
428
|
|
|
431
|
-
|
|
429
|
+
ray.origin = stepRayOrigin( ray.origin, ray.direction, - surfaceHit.faceNormal, surfaceHit.dist );
|
|
432
430
|
continue;
|
|
433
431
|
|
|
434
432
|
}
|
|
435
433
|
|
|
436
|
-
|
|
434
|
+
scatterRec = bsdfSample( - ray.direction, surf );
|
|
435
|
+
state.isShadowRay = scatterRec.specularPdf < sobol( 4 );
|
|
437
436
|
|
|
438
|
-
|
|
439
|
-
|
|
437
|
+
bool isBelowSurface = ! surf.volumeParticle && dot( scatterRec.direction, surf.faceNormal ) < 0.0;
|
|
438
|
+
vec3 hitPoint = stepRayOrigin( ray.origin, ray.direction, isBelowSurface ? - surf.faceNormal : surf.faceNormal, surfaceHit.dist );
|
|
440
439
|
|
|
441
|
-
|
|
442
|
-
mat3 clearcoatInvBasis = inverse( clearcoatNormalBasis );
|
|
443
|
-
|
|
444
|
-
vec3 outgoing = - normalize( invBasis * rayDirection );
|
|
445
|
-
vec3 clearcoatOutgoing = - normalize( clearcoatInvBasis * rayDirection );
|
|
446
|
-
sampleRec = bsdfSample( outgoing, clearcoatOutgoing, normalBasis, invBasis, clearcoatNormalBasis, clearcoatInvBasis, surf );
|
|
447
|
-
|
|
448
|
-
bool wasBelowSurface = ! surf.volumeParticle && dot( rayDirection, faceNormal ) > 0.0;
|
|
449
|
-
isShadowRay = sampleRec.specularPdf < sobol( 4 );
|
|
450
|
-
|
|
451
|
-
vec3 prevRayDirection = rayDirection;
|
|
452
|
-
rayDirection = normalize( normalBasis * sampleRec.direction );
|
|
453
|
-
|
|
454
|
-
bool isBelowSurface = ! surf.volumeParticle && dot( rayDirection, faceNormal ) < 0.0;
|
|
455
|
-
rayOrigin = stepRayOrigin( rayOrigin, prevRayDirection, isBelowSurface ? - faceNormal : faceNormal, dist );
|
|
456
|
-
|
|
457
|
-
// direct env map sampling
|
|
440
|
+
// next event estimation
|
|
458
441
|
#if FEATURE_MIS
|
|
459
442
|
|
|
460
|
-
|
|
461
|
-
if( lightsDenom != 0.0 && sobol( 5 ) < float( lights.count ) / lightsDenom ) {
|
|
462
|
-
|
|
463
|
-
// sample a light or environment
|
|
464
|
-
LightSampleRecord lightSampleRec = randomLightSample( lights.tex, iesProfiles, lights.count, rayOrigin, sobol3( 6 ) );
|
|
465
|
-
|
|
466
|
-
bool isSampleBelowSurface = ! surf.volumeParticle && dot( faceNormal, lightSampleRec.direction ) < 0.0;
|
|
467
|
-
if ( isSampleBelowSurface ) {
|
|
468
|
-
|
|
469
|
-
lightSampleRec.pdf = 0.0;
|
|
443
|
+
gl_FragColor.rgb += directLightContribution( - ray.direction, surf, state, hitPoint );
|
|
470
444
|
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
// check if a ray could even reach the light area
|
|
474
|
-
vec3 attenuatedColor;
|
|
475
|
-
if (
|
|
476
|
-
lightSampleRec.pdf > 0.0 &&
|
|
477
|
-
isDirectionValid( lightSampleRec.direction, surf.normal, faceNormal ) &&
|
|
478
|
-
! attenuateHit( bvh, rayOrigin, lightSampleRec.direction, lightSampleRec.dist, bounces - i, transmissiveTraversals, isShadowRay, fogMaterial, attenuatedColor )
|
|
479
|
-
) {
|
|
480
|
-
|
|
481
|
-
// get the material pdf
|
|
482
|
-
vec3 sampleColor;
|
|
483
|
-
float lightMaterialPdf = bsdfResult( outgoing, clearcoatOutgoing, normalize( invBasis * lightSampleRec.direction ), normalize( clearcoatInvBasis * lightSampleRec.direction ), surf, sampleColor );
|
|
484
|
-
bool isValidSampleColor = all( greaterThanEqual( sampleColor, vec3( 0.0 ) ) );
|
|
485
|
-
if ( lightMaterialPdf > 0.0 && isValidSampleColor ) {
|
|
486
|
-
|
|
487
|
-
// weight the direct light contribution
|
|
488
|
-
float lightPdf = lightSampleRec.pdf / lightsDenom;
|
|
489
|
-
float misWeight = lightSampleRec.type == SPOT_LIGHT_TYPE || lightSampleRec.type == DIR_LIGHT_TYPE || lightSampleRec.type == POINT_LIGHT_TYPE ? 1.0 : misHeuristic( lightPdf, lightMaterialPdf );
|
|
490
|
-
gl_FragColor.rgb += attenuatedColor * lightSampleRec.emission * throughputColor * sampleColor * misWeight / lightPdf;
|
|
491
|
-
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
} else {
|
|
497
|
-
|
|
498
|
-
// find a sample in the environment map to include in the contribution
|
|
499
|
-
vec3 envColor, envDirection;
|
|
500
|
-
float envPdf = sampleEquirectProbability( envMapInfo, sobol2( 7 ), envColor, envDirection );
|
|
501
|
-
envDirection = invEnvRotation3x3 * envDirection;
|
|
502
|
-
|
|
503
|
-
// this env sampling is not set up for transmissive sampling and yields overly bright
|
|
504
|
-
// results so we ignore the sample in this case.
|
|
505
|
-
// TODO: this should be improved but how? The env samples could traverse a few layers?
|
|
506
|
-
bool isSampleBelowSurface = ! surf.volumeParticle && dot( faceNormal, envDirection ) < 0.0;
|
|
507
|
-
if ( isSampleBelowSurface ) {
|
|
508
|
-
|
|
509
|
-
envPdf = 0.0;
|
|
510
|
-
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// check if a ray could even reach the surface
|
|
514
|
-
vec3 attenuatedColor;
|
|
515
|
-
if (
|
|
516
|
-
envPdf > 0.0 &&
|
|
517
|
-
isDirectionValid( envDirection, surf.normal, faceNormal ) &&
|
|
518
|
-
! attenuateHit( bvh, rayOrigin, envDirection, INFINITY, bounces - i, transmissiveTraversals, isShadowRay, fogMaterial, attenuatedColor )
|
|
519
|
-
) {
|
|
520
|
-
|
|
521
|
-
// get the material pdf
|
|
522
|
-
vec3 sampleColor;
|
|
523
|
-
float envMaterialPdf = bsdfResult( outgoing, clearcoatOutgoing, normalize( invBasis * envDirection ), normalize( clearcoatInvBasis * envDirection ), surf, sampleColor );
|
|
524
|
-
bool isValidSampleColor = all( greaterThanEqual( sampleColor, vec3( 0.0 ) ) );
|
|
525
|
-
if ( envMaterialPdf > 0.0 && isValidSampleColor ) {
|
|
526
|
-
|
|
527
|
-
// weight the direct light contribution
|
|
528
|
-
envPdf /= lightsDenom;
|
|
529
|
-
float misWeight = misHeuristic( envPdf, envMaterialPdf );
|
|
530
|
-
gl_FragColor.rgb += attenuatedColor * environmentIntensity * envColor * throughputColor * sampleColor * misWeight / envPdf;
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
}
|
|
537
445
|
#endif
|
|
538
446
|
|
|
539
447
|
// accumulate a roughness value to offset diffuse, specular, diffuse rays that have high contribution
|
|
540
448
|
// to a single pixel resulting in fireflies
|
|
449
|
+
// TODO: handle transmissive surfaces
|
|
541
450
|
if ( ! surf.volumeParticle && ! isBelowSurface ) {
|
|
542
451
|
|
|
543
452
|
// determine if this is a rough normal or not by checking how far off straight up it is
|
|
544
|
-
vec3 halfVector = normalize(
|
|
545
|
-
|
|
546
|
-
|
|
453
|
+
vec3 halfVector = normalize( - ray.direction + scatterRec.direction );
|
|
454
|
+
state.accumulatedRoughness += max(
|
|
455
|
+
sin( acosApprox( dot( halfVector, surf.normal ) ) ),
|
|
456
|
+
sin( acosApprox( dot( halfVector, surf.clearcoatNormal ) ) )
|
|
457
|
+
);
|
|
547
458
|
|
|
548
|
-
transmissiveRay = false;
|
|
459
|
+
state.transmissiveRay = false;
|
|
549
460
|
|
|
550
461
|
}
|
|
551
462
|
|
|
552
|
-
//
|
|
553
|
-
|
|
554
|
-
bool isTransmissiveRay = ! surf.volumeParticle && dot( rayDirection, faceNormal * side ) < 0.0;
|
|
555
|
-
if ( ( isTransmissiveRay || isBelowSurface ) && transmissiveTraversals > 0 ) {
|
|
463
|
+
// accumulate emissive color
|
|
464
|
+
gl_FragColor.rgb += ( surf.emission * state.throughputColor );
|
|
556
465
|
|
|
557
|
-
|
|
558
|
-
|
|
466
|
+
// skip the sample if our PDF or ray is impossible
|
|
467
|
+
if ( scatterRec.pdf <= 0.0 || ! isDirectionValid( scatterRec.direction, surf.normal, surf.faceNormal ) ) {
|
|
468
|
+
|
|
469
|
+
break;
|
|
559
470
|
|
|
560
471
|
}
|
|
561
472
|
|
|
562
|
-
|
|
563
|
-
|
|
473
|
+
// if we're bouncing around the inside a transmissive material then decrement
|
|
474
|
+
// perform this separate from a bounce
|
|
475
|
+
bool isTransmissiveRay = ! surf.volumeParticle && dot( scatterRec.direction, surf.faceNormal * surfaceHit.side ) < 0.0;
|
|
476
|
+
if ( ( isTransmissiveRay || isBelowSurface ) && state.transmissiveTraversals > 0 ) {
|
|
564
477
|
|
|
565
|
-
transmissiveTraversals --;
|
|
478
|
+
state.transmissiveTraversals --;
|
|
566
479
|
i --;
|
|
567
480
|
|
|
568
481
|
}
|
|
569
|
-
#endif
|
|
570
482
|
|
|
571
|
-
//
|
|
572
|
-
gl_FragColor.rgb += ( surf.emission * throughputColor );
|
|
483
|
+
//
|
|
573
484
|
|
|
574
|
-
//
|
|
575
|
-
|
|
485
|
+
// handle throughput color transformation
|
|
486
|
+
// attenuate the throughput color by the medium color
|
|
487
|
+
if ( ! surf.frontFace ) {
|
|
576
488
|
|
|
577
|
-
|
|
489
|
+
state.throughputColor *= transmissionAttenuation( surfaceHit.dist, surf.attenuationColor, surf.attenuationDistance );
|
|
578
490
|
|
|
579
491
|
}
|
|
580
492
|
|
|
@@ -583,10 +495,10 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
583
495
|
// russian roulette path termination
|
|
584
496
|
// https://www.arnoldrenderer.com/research/physically_based_shader_design_in_arnold.pdf
|
|
585
497
|
uint minBounces = 3u;
|
|
586
|
-
float depthProb = float(
|
|
498
|
+
float depthProb = float( state.depth < minBounces );
|
|
587
499
|
|
|
588
|
-
float rrProb = luminance( throughputColor *
|
|
589
|
-
rrProb /= luminance( throughputColor );
|
|
500
|
+
float rrProb = luminance( state.throughputColor * scatterRec.color / scatterRec.pdf );
|
|
501
|
+
rrProb /= luminance( state.throughputColor );
|
|
590
502
|
rrProb = sqrt( rrProb );
|
|
591
503
|
rrProb = max( rrProb, depthProb );
|
|
592
504
|
rrProb = min( rrProb, 1.0 );
|
|
@@ -597,31 +509,41 @@ export class PhysicalPathTracingMaterial extends MaterialBase {
|
|
|
597
509
|
}
|
|
598
510
|
|
|
599
511
|
// perform sample clamping here to avoid bright pixels
|
|
600
|
-
throughputColor *= min( 1.0 / rrProb, 20.0 );
|
|
512
|
+
state.throughputColor *= min( 1.0 / rrProb, 20.0 );
|
|
601
513
|
|
|
602
514
|
#endif
|
|
603
515
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
if ( side == - 1.0 ) {
|
|
608
|
-
|
|
609
|
-
throughputColor *= transmissionAttenuation( dist, surf.attenuationColor, surf.attenuationDistance );
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
// discard the sample if there are any NaNs
|
|
614
|
-
if ( any( isnan( throughputColor ) ) || any( isinf( throughputColor ) ) ) {
|
|
516
|
+
// adjust the throughput and discard and exit if we find discard the sample if there are any NaNs
|
|
517
|
+
state.throughputColor *= scatterRec.color / scatterRec.pdf;
|
|
518
|
+
if ( any( isnan( state.throughputColor ) ) || any( isinf( state.throughputColor ) ) ) {
|
|
615
519
|
|
|
616
520
|
break;
|
|
617
521
|
|
|
618
522
|
}
|
|
619
523
|
|
|
524
|
+
//
|
|
525
|
+
|
|
526
|
+
// prepare for next ray
|
|
527
|
+
ray.direction = scatterRec.direction;
|
|
528
|
+
ray.origin = hitPoint;
|
|
620
529
|
|
|
621
530
|
}
|
|
622
531
|
|
|
623
532
|
gl_FragColor.a *= opacity;
|
|
624
533
|
|
|
534
|
+
#if DEBUG_MODE == 1
|
|
535
|
+
|
|
536
|
+
// output the number of rays checked in the path and number of
|
|
537
|
+
// transmissive rays encountered.
|
|
538
|
+
gl_FragColor.rgb = vec3(
|
|
539
|
+
float( state.depth ),
|
|
540
|
+
transmissiveBounces - state.transmissiveTraversals,
|
|
541
|
+
0.0
|
|
542
|
+
);
|
|
543
|
+
gl_FragColor.a = 1.0;
|
|
544
|
+
|
|
545
|
+
#endif
|
|
546
|
+
|
|
625
547
|
}
|
|
626
548
|
|
|
627
549
|
`
|