three-gpu-pathtracer 0.0.13 → 0.0.14

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.
Files changed (78) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +981 -961
  3. package/build/index.module.js +6965 -6508
  4. package/build/index.module.js.map +1 -1
  5. package/build/index.umd.cjs +6959 -6505
  6. package/build/index.umd.cjs.map +1 -1
  7. package/package.json +73 -73
  8. package/src/core/DynamicPathTracingSceneGenerator.js +119 -119
  9. package/src/core/MaterialReducer.js +256 -256
  10. package/src/core/PathTracingRenderer.js +346 -346
  11. package/src/core/PathTracingSceneGenerator.js +69 -69
  12. package/src/core/QuiltPathTracingRenderer.js +223 -223
  13. package/src/index.js +36 -40
  14. package/src/materials/MaterialBase.js +56 -56
  15. package/src/materials/{GraphMaterial.js → debug/GraphMaterial.js} +243 -243
  16. package/src/materials/{AlphaDisplayMaterial.js → fullscreen/AlphaDisplayMaterial.js} +48 -48
  17. package/src/materials/{BlendMaterial.js → fullscreen/BlendMaterial.js} +67 -67
  18. package/src/materials/{DenoiseMaterial.js → fullscreen/DenoiseMaterial.js} +142 -142
  19. package/src/materials/{LambertPathTracingMaterial.js → pathtracing/LambertPathTracingMaterial.js} +296 -285
  20. package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +635 -0
  21. package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +179 -0
  22. package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +81 -0
  23. package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +317 -0
  24. package/src/materials/pathtracing/glsl/traceScene.glsl.js +54 -0
  25. package/src/materials/{AmbientOcclusionMaterial.js → surface/AmbientOcclusionMaterial.js} +207 -199
  26. package/src/materials/surface/FogVolumeMaterial.js +23 -0
  27. package/src/objects/EquirectCamera.js +13 -13
  28. package/src/objects/PhysicalCamera.js +28 -28
  29. package/src/objects/PhysicalSpotLight.js +14 -14
  30. package/src/objects/ShapedAreaLight.js +12 -12
  31. package/src/shader/bsdf/bsdfSampling.glsl.js +490 -0
  32. package/src/shader/bsdf/fog.glsl.js +23 -0
  33. package/src/shader/bsdf/ggx.glsl.js +102 -0
  34. package/src/shader/bsdf/iridescence.glsl.js +135 -0
  35. package/src/shader/bsdf/sheen.glsl.js +98 -0
  36. package/src/shader/{shaderLayerTexelFetchFunctions.js → common/arraySamplerTexelFetch.glsl.js} +25 -25
  37. package/src/shader/common/bvhAnyHit.glsl.js +76 -0
  38. package/src/shader/common/fresnel.glsl.js +98 -0
  39. package/src/shader/common/intersectShapes.glsl.js +62 -0
  40. package/src/shader/common/math.glsl.js +81 -0
  41. package/src/shader/common/utils.glsl.js +116 -0
  42. package/src/shader/{shaderRandFunctions.js → rand/pcg.glsl.js} +57 -57
  43. package/src/shader/{shaderSobolSampling.js → rand/sobol.glsl.js} +256 -256
  44. package/src/shader/sampling/equirectSampling.glsl.js +62 -0
  45. package/src/shader/sampling/lightSampling.glsl.js +223 -0
  46. package/src/shader/sampling/shapeSampling.glsl.js +86 -0
  47. package/src/shader/structs/cameraStruct.glsl.js +13 -0
  48. package/src/shader/structs/equirectStruct.glsl.js +14 -0
  49. package/src/shader/structs/fogMaterialBvh.glsl.js +62 -0
  50. package/src/shader/structs/lightsStruct.glsl.js +78 -0
  51. package/src/shader/{shaderStructs.js → structs/materialStruct.glsl.js} +207 -327
  52. package/src/textures/GradientEquirectTexture.js +35 -35
  53. package/src/textures/ProceduralEquirectTexture.js +75 -75
  54. package/src/uniforms/AttributesTextureArray.js +35 -35
  55. package/src/uniforms/EquirectHdrInfoUniform.js +277 -273
  56. package/src/uniforms/FloatAttributeTextureArray.js +169 -169
  57. package/src/uniforms/IESProfilesTexture.js +100 -100
  58. package/src/uniforms/LightsInfoUniformStruct.js +212 -212
  59. package/src/uniforms/MaterialsTexture.js +503 -426
  60. package/src/uniforms/PhysicalCameraUniform.js +36 -36
  61. package/src/uniforms/RenderTarget2DArray.js +97 -97
  62. package/src/uniforms/utils.js +30 -30
  63. package/src/utils/BlurredEnvMapGenerator.js +116 -116
  64. package/src/utils/GeometryPreparationUtils.js +214 -214
  65. package/src/utils/IESLoader.js +325 -325
  66. package/src/utils/SobolNumberMapGenerator.js +80 -80
  67. package/src/utils/UVUnwrapper.js +101 -101
  68. package/src/utils/macroify.js +9 -0
  69. package/src/workers/PathTracingSceneWorker.js +42 -42
  70. package/src/materials/PhysicalPathTracingMaterial.js +0 -1013
  71. package/src/shader/shaderBvhAnyHit.js +0 -76
  72. package/src/shader/shaderEnvMapSampling.js +0 -58
  73. package/src/shader/shaderGGXFunctions.js +0 -100
  74. package/src/shader/shaderIridescenceFunctions.js +0 -135
  75. package/src/shader/shaderLightSampling.js +0 -229
  76. package/src/shader/shaderMaterialSampling.js +0 -510
  77. package/src/shader/shaderSheenFunctions.js +0 -98
  78. package/src/shader/shaderUtils.js +0 -377
@@ -0,0 +1,179 @@
1
+ export const attenuateHitGLSL = /* glsl */`
2
+
3
+ // step through multiple surface hits and accumulate color attenuation based on transmissive surfaces
4
+ // returns true if a solid surface was hit
5
+ bool attenuateHit(
6
+ BVH bvh, vec3 rayOrigin, vec3 rayDirection, float rayDist,
7
+ int traversals, int transmissiveTraversals, bool isShadowRay,
8
+ Material fogMaterial,
9
+ out vec3 color
10
+ ) {
11
+
12
+ vec3 ogRayOrigin = rayOrigin;
13
+
14
+ // hit results
15
+ uvec4 faceIndices = uvec4( 0u );
16
+ vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
17
+ vec3 barycoord = vec3( 0.0 );
18
+ float side = 1.0;
19
+ float dist = 0.0;
20
+ LightSampleRecord lightSampleRec;
21
+
22
+ color = vec3( 1.0 );
23
+
24
+ // TODO: we should be using sobol sampling here instead of rand but the sobol bounce and path indices need to be incremented
25
+ // and then reset.
26
+ for ( int i = 0; i < traversals; i ++ ) {
27
+
28
+ int hitType = traceScene(
29
+ rayOrigin, rayDirection,
30
+ bvh, lights, fogMaterial,
31
+ faceIndices, faceNormal, barycoord, side, dist,
32
+ lightSampleRec
33
+ );
34
+
35
+ if ( hitType == FOG_HIT ) {
36
+
37
+ return true;
38
+
39
+ } else if ( hitType == LIGHT_HIT ) {
40
+
41
+ float totalDist = distance( ogRayOrigin, rayOrigin + rayDirection * lightSampleRec.dist );
42
+ return totalDist < rayDist - max( totalDist, rayDist ) * 1e-4;
43
+
44
+ } else if ( hitType == SURFACE_HIT ) {
45
+
46
+ float totalDist = distance( ogRayOrigin, rayOrigin + rayDirection * dist );
47
+ if ( totalDist > rayDist ) {
48
+
49
+ return false;
50
+
51
+ }
52
+
53
+ // TODO: attenuate the contribution based on the PDF of the resulting ray including refraction values
54
+ // Should be able to work using the material BSDF functions which will take into account specularity, etc.
55
+ // TODO: should we account for emissive surfaces here?
56
+
57
+ uint materialIndex = uTexelFetch1D( materialIndexAttribute, faceIndices.x ).r;
58
+ Material material = readMaterialInfo( materials, materialIndex );
59
+
60
+ // adjust the ray to the new surface
61
+ bool isEntering = side == 1.0;
62
+ rayOrigin = stepRayOrigin( rayOrigin, rayDirection, - faceNormal, dist );
63
+
64
+ #if FEATURE_FOG
65
+
66
+ if ( material.fogVolume ) {
67
+
68
+ fogMaterial = material;
69
+ fogMaterial.fogVolume = side == 1.0;
70
+ i -= sign( transmissiveTraversals );
71
+ transmissiveTraversals --;
72
+ continue;
73
+
74
+ }
75
+
76
+ #endif
77
+
78
+ if ( ! material.castShadow && isShadowRay ) {
79
+
80
+ continue;
81
+
82
+ }
83
+
84
+ vec2 uv = textureSampleBarycoord( attributesArray, ATTR_UV, barycoord, faceIndices.xyz ).xy;
85
+ vec4 vertexColor = textureSampleBarycoord( attributesArray, ATTR_COLOR, barycoord, faceIndices.xyz );
86
+
87
+ // albedo
88
+ vec4 albedo = vec4( material.color, material.opacity );
89
+ if ( material.map != - 1 ) {
90
+
91
+ vec3 uvPrime = material.mapTransform * vec3( uv, 1 );
92
+ albedo *= texture2D( textures, vec3( uvPrime.xy, material.map ) );
93
+
94
+ }
95
+
96
+ if ( material.vertexColors ) {
97
+
98
+ albedo *= vertexColor;
99
+
100
+ }
101
+
102
+ // alphaMap
103
+ if ( material.alphaMap != - 1 ) {
104
+
105
+ albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
106
+
107
+ }
108
+
109
+ // transmission
110
+ float transmission = material.transmission;
111
+ if ( material.transmissionMap != - 1 ) {
112
+
113
+ vec3 uvPrime = material.transmissionMapTransform * vec3( uv, 1 );
114
+ transmission *= texture2D( textures, vec3( uvPrime.xy, material.transmissionMap ) ).r;
115
+
116
+ }
117
+
118
+ // metalness
119
+ float metalness = material.metalness;
120
+ if ( material.metalnessMap != - 1 ) {
121
+
122
+ vec3 uvPrime = material.metalnessMapTransform * vec3( uv, 1 );
123
+ metalness *= texture2D( textures, vec3( uvPrime.xy, material.metalnessMap ) ).b;
124
+
125
+ }
126
+
127
+ float alphaTest = material.alphaTest;
128
+ bool useAlphaTest = alphaTest != 0.0;
129
+ float transmissionFactor = ( 1.0 - metalness ) * transmission;
130
+ if (
131
+ transmissionFactor < rand() && ! (
132
+ // material sidedness
133
+ material.side != 0.0 && side == material.side
134
+
135
+ // alpha test
136
+ || useAlphaTest && albedo.a < alphaTest
137
+
138
+ // opacity
139
+ || material.transparent && ! useAlphaTest && albedo.a < rand()
140
+ )
141
+ ) {
142
+
143
+ return true;
144
+
145
+ }
146
+
147
+ if ( side == 1.0 && isEntering ) {
148
+
149
+ // only attenuate by surface color on the way in
150
+ color *= mix( vec3( 1.0 ), albedo.rgb, transmissionFactor );
151
+
152
+ } else if ( side == - 1.0 ) {
153
+
154
+ // attenuate by medium once we hit the opposite side of the model
155
+ color *= transmissionAttenuation( dist, material.attenuationColor, material.attenuationDistance );
156
+
157
+ }
158
+
159
+ bool isTransmissiveRay = dot( rayDirection, faceNormal * side ) < 0.0;
160
+ if ( ( isTransmissiveRay || isEntering ) && transmissiveTraversals > 0 ) {
161
+
162
+ i -= sign( transmissiveTraversals );
163
+ transmissiveTraversals --;
164
+
165
+ }
166
+
167
+ } else {
168
+
169
+ return false;
170
+
171
+ }
172
+
173
+ }
174
+
175
+ return true;
176
+
177
+ }
178
+
179
+ `;
@@ -0,0 +1,81 @@
1
+ export const cameraUtilsGLSL = /* glsl */`
2
+
3
+ vec3 ndcToRayOrigin( vec2 coord ) {
4
+
5
+ vec4 rayOrigin4 = cameraWorldMatrix * invProjectionMatrix * vec4( coord, - 1.0, 1.0 );
6
+ return rayOrigin4.xyz / rayOrigin4.w;
7
+ }
8
+
9
+ void getCameraRay( out vec3 rayDirection, out vec3 rayOrigin ) {
10
+
11
+ vec2 ssd = vec2( 1.0 ) / resolution;
12
+
13
+ // Jitter the camera ray by finding a uv coordinate at a random sample
14
+ // around this pixel's UV coordinate for AA
15
+ vec2 ruv = sobol2( 0 );
16
+ vec2 jitteredUv = vUv + vec2( tentFilter( ruv.x ) * ssd.x, tentFilter( ruv.y ) * ssd.y );
17
+
18
+ #if CAMERA_TYPE == 2
19
+
20
+ // Equirectangular projection
21
+ vec4 rayDirection4 = vec4( equirectUvToDirection( jitteredUv ), 0.0 );
22
+ vec4 rayOrigin4 = vec4( 0.0, 0.0, 0.0, 1.0 );
23
+
24
+ rayDirection4 = cameraWorldMatrix * rayDirection4;
25
+ rayOrigin4 = cameraWorldMatrix * rayOrigin4;
26
+
27
+ rayDirection = normalize( rayDirection4.xyz );
28
+ rayOrigin = rayOrigin4.xyz / rayOrigin4.w;
29
+
30
+ #else
31
+
32
+ // get [- 1, 1] normalized device coordinates
33
+ vec2 ndc = 2.0 * jitteredUv - vec2( 1.0 );
34
+ rayOrigin = ndcToRayOrigin( ndc );
35
+
36
+ #if CAMERA_TYPE == 1
37
+
38
+ // Orthographic projection
39
+ rayDirection = ( cameraWorldMatrix * vec4( 0.0, 0.0, - 1.0, 0.0 ) ).xyz;
40
+ rayDirection = normalize( rayDirection );
41
+
42
+ #else
43
+
44
+ // Perspective projection
45
+ rayDirection = normalize( mat3(cameraWorldMatrix) * ( invProjectionMatrix * vec4( ndc, 0.0, 1.0 ) ).xyz );
46
+
47
+ #endif
48
+
49
+ #endif
50
+
51
+ #if FEATURE_DOF
52
+ {
53
+
54
+ // depth of field
55
+ vec3 focalPoint = rayOrigin + normalize( rayDirection ) * physicalCamera.focusDistance;
56
+
57
+ // get the aperture sample
58
+ // if blades === 0 then we assume a circle
59
+ vec3 shapeUVW= sobol3( 1 );
60
+ int blades = physicalCamera.apertureBlades;
61
+ float anamorphicRatio = physicalCamera.anamorphicRatio;
62
+ vec2 apertureSample = blades == 0 ? sampleCircle( shapeUVW.xy ) : sampleRegularPolygon( blades, shapeUVW );
63
+ apertureSample *= physicalCamera.bokehSize * 0.5 * 1e-3;
64
+
65
+ // rotate the aperture shape
66
+ apertureSample =
67
+ rotateVector( apertureSample, physicalCamera.apertureRotation ) *
68
+ saturate( vec2( anamorphicRatio, 1.0 / anamorphicRatio ) );
69
+
70
+ // create the new ray
71
+ rayOrigin += ( cameraWorldMatrix * vec4( apertureSample, 0.0, 0.0 ) ).xyz;
72
+ rayDirection = focalPoint - rayOrigin;
73
+
74
+ }
75
+ #endif
76
+
77
+ rayDirection = normalize( rayDirection );
78
+
79
+ }
80
+
81
+ `;
@@ -0,0 +1,317 @@
1
+
2
+ export const getSurfaceRecordGLSL = /* glsl */`
3
+
4
+ #define SKIP_SURFACE 0
5
+ #define HIT_SURFACE 1
6
+ int getSurfaceRecord(
7
+ Material material, sampler2DArray attributesArray,
8
+ float side, vec3 barycoord, uvec4 faceIndices, vec3 faceNormal, float accumulatedRoughness,
9
+
10
+ out SurfaceRecord surf
11
+ ) {
12
+
13
+ if ( material.fogVolume ) {
14
+
15
+ vec3 normal = vec3( 0, 0, 1 );
16
+
17
+ SurfaceRecord fogSurface;
18
+ fogSurface.volumeParticle = true;
19
+ fogSurface.color = material.color;
20
+ fogSurface.emission = material.emissiveIntensity * material.emissive;
21
+ fogSurface.normal = normal;
22
+ fogSurface.faceNormal = normal;
23
+ fogSurface.clearcoatNormal = normal;
24
+
25
+ surf = fogSurface;
26
+ return HIT_SURFACE;
27
+
28
+ }
29
+
30
+ // uv coord for textures
31
+ vec2 uv = textureSampleBarycoord( attributesArray, ATTR_UV, barycoord, faceIndices.xyz ).xy;
32
+ vec4 vertexColor = textureSampleBarycoord( attributesArray, ATTR_COLOR, barycoord, faceIndices.xyz );
33
+
34
+ // albedo
35
+ vec4 albedo = vec4( material.color, material.opacity );
36
+ if ( material.map != - 1 ) {
37
+
38
+ vec3 uvPrime = material.mapTransform * vec3( uv, 1 );
39
+ albedo *= texture2D( textures, vec3( uvPrime.xy, material.map ) );
40
+ }
41
+
42
+ if ( material.vertexColors ) {
43
+
44
+ albedo *= vertexColor;
45
+
46
+ }
47
+
48
+ // alphaMap
49
+ if ( material.alphaMap != - 1 ) {
50
+
51
+ albedo.a *= texture2D( textures, vec3( uv, material.alphaMap ) ).x;
52
+
53
+ }
54
+
55
+ // possibly skip this sample if it's transparent, alpha test is enabled, or we hit the wrong material side
56
+ // and it's single sided.
57
+ // - alpha test is disabled when it === 0
58
+ // - the material sidedness test is complicated because we want light to pass through the back side but still
59
+ // be able to see the front side. This boolean checks if the side we hit is the front side on the first ray
60
+ // and we're rendering the other then we skip it. Do the opposite on subsequent bounces to get incoming light.
61
+ float alphaTest = material.alphaTest;
62
+ bool useAlphaTest = alphaTest != 0.0;
63
+ if (
64
+ // material sidedness
65
+ material.side != 0.0 && side != material.side
66
+
67
+ // alpha test
68
+ || useAlphaTest && albedo.a < alphaTest
69
+
70
+ // opacity
71
+ || material.transparent && ! useAlphaTest && albedo.a < sobol( 3 )
72
+ ) {
73
+
74
+ return SKIP_SURFACE;
75
+
76
+ }
77
+
78
+ // fetch the interpolated smooth normal
79
+ vec3 normal = normalize( textureSampleBarycoord(
80
+ attributesArray,
81
+ ATTR_NORMAL,
82
+ barycoord,
83
+ faceIndices.xyz
84
+ ).xyz );
85
+
86
+ // roughness
87
+ float roughness = material.roughness;
88
+ if ( material.roughnessMap != - 1 ) {
89
+
90
+ vec3 uvPrime = material.roughnessMapTransform * vec3( uv, 1 );
91
+ roughness *= texture2D( textures, vec3( uvPrime.xy, material.roughnessMap ) ).g;
92
+
93
+ }
94
+
95
+ // metalness
96
+ float metalness = material.metalness;
97
+ if ( material.metalnessMap != - 1 ) {
98
+
99
+ vec3 uvPrime = material.metalnessMapTransform * vec3( uv, 1 );
100
+ metalness *= texture2D( textures, vec3( uvPrime.xy, material.metalnessMap ) ).b;
101
+
102
+ }
103
+
104
+ // emission
105
+ vec3 emission = material.emissiveIntensity * material.emissive;
106
+ if ( material.emissiveMap != - 1 ) {
107
+
108
+ vec3 uvPrime = material.emissiveMapTransform * vec3( uv, 1 );
109
+ emission *= texture2D( textures, vec3( uvPrime.xy, material.emissiveMap ) ).xyz;
110
+
111
+ }
112
+
113
+ // transmission
114
+ float transmission = material.transmission;
115
+ if ( material.transmissionMap != - 1 ) {
116
+
117
+ vec3 uvPrime = material.transmissionMapTransform * vec3( uv, 1 );
118
+ transmission *= texture2D( textures, vec3( uvPrime.xy, material.transmissionMap ) ).r;
119
+
120
+ }
121
+
122
+ // normal
123
+ if ( material.flatShading ) {
124
+
125
+ // if we're rendering a flat shaded object then use the face normals - the face normal
126
+ // is provided based on the side the ray hits the mesh so flip it to align with the
127
+ // interpolated vertex normals.
128
+ normal = faceNormal * side;
129
+
130
+ }
131
+
132
+ vec3 baseNormal = normal;
133
+ if ( material.normalMap != - 1 ) {
134
+
135
+ vec4 tangentSample = textureSampleBarycoord(
136
+ attributesArray,
137
+ ATTR_TANGENT,
138
+ barycoord,
139
+ faceIndices.xyz
140
+ );
141
+
142
+ // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
143
+ // resulting in NaNs and slow path tracing.
144
+ if ( length( tangentSample.xyz ) > 0.0 ) {
145
+
146
+ vec3 tangent = normalize( tangentSample.xyz );
147
+ vec3 bitangent = normalize( cross( normal, tangent ) * tangentSample.w );
148
+ mat3 vTBN = mat3( tangent, bitangent, normal );
149
+
150
+ vec3 uvPrime = material.normalMapTransform * vec3( uv, 1 );
151
+ vec3 texNormal = texture2D( textures, vec3( uvPrime.xy, material.normalMap ) ).xyz * 2.0 - 1.0;
152
+ texNormal.xy *= material.normalScale;
153
+ normal = vTBN * texNormal;
154
+
155
+ }
156
+
157
+ }
158
+
159
+ normal *= side;
160
+
161
+ // clearcoat
162
+ float clearcoat = material.clearcoat;
163
+ if ( material.clearcoatMap != - 1 ) {
164
+
165
+ vec3 uvPrime = material.clearcoatMapTransform * vec3( uv, 1 );
166
+ clearcoat *= texture2D( textures, vec3( uvPrime.xy, material.clearcoatMap ) ).r;
167
+
168
+ }
169
+
170
+ // clearcoatRoughness
171
+ float clearcoatRoughness = material.clearcoatRoughness;
172
+ if ( material.clearcoatRoughnessMap != - 1 ) {
173
+
174
+ vec3 uvPrime = material.clearcoatRoughnessMapTransform * vec3( uv, 1 );
175
+ clearcoatRoughness *= texture2D( textures, vec3( uvPrime.xy, material.clearcoatRoughnessMap ) ).g;
176
+
177
+ }
178
+
179
+ // clearcoatNormal
180
+ vec3 clearcoatNormal = baseNormal;
181
+ if ( material.clearcoatNormalMap != - 1 ) {
182
+
183
+ vec4 tangentSample = textureSampleBarycoord(
184
+ attributesArray,
185
+ ATTR_TANGENT,
186
+ barycoord,
187
+ faceIndices.xyz
188
+ );
189
+
190
+ // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
191
+ // resulting in NaNs and slow path tracing.
192
+ if ( length( tangentSample.xyz ) > 0.0 ) {
193
+
194
+ vec3 tangent = normalize( tangentSample.xyz );
195
+ vec3 bitangent = normalize( cross( clearcoatNormal, tangent ) * tangentSample.w );
196
+ mat3 vTBN = mat3( tangent, bitangent, clearcoatNormal );
197
+
198
+ vec3 uvPrime = material.clearcoatNormalMapTransform * vec3( uv, 1 );
199
+ vec3 texNormal = texture2D( textures, vec3( uvPrime.xy, material.clearcoatNormalMap ) ).xyz * 2.0 - 1.0;
200
+ texNormal.xy *= material.clearcoatNormalScale;
201
+ clearcoatNormal = vTBN * texNormal;
202
+
203
+ }
204
+
205
+ }
206
+
207
+ clearcoatNormal *= side;
208
+
209
+ // sheenColor
210
+ vec3 sheenColor = material.sheenColor;
211
+ if ( material.sheenColorMap != - 1 ) {
212
+
213
+ vec3 uvPrime = material.sheenColorMapTransform * vec3( uv, 1 );
214
+ sheenColor *= texture2D( textures, vec3( uvPrime.xy, material.sheenColorMap ) ).rgb;
215
+
216
+ }
217
+
218
+ // sheenRoughness
219
+ float sheenRoughness = material.sheenRoughness;
220
+ if ( material.sheenRoughnessMap != - 1 ) {
221
+
222
+ vec3 uvPrime = material.sheenRoughnessMapTransform * vec3( uv, 1 );
223
+ sheenRoughness *= texture2D( textures, vec3( uvPrime.xy, material.sheenRoughnessMap ) ).a;
224
+
225
+ }
226
+
227
+ // iridescence
228
+ float iridescence = material.iridescence;
229
+ if ( material.iridescenceMap != - 1 ) {
230
+
231
+ vec3 uvPrime = material.iridescenceMapTransform * vec3( uv, 1 );
232
+ iridescence *= texture2D( textures, vec3( uvPrime.xy, material.iridescenceMap ) ).r;
233
+
234
+ }
235
+
236
+ // iridescence thickness
237
+ float iridescenceThickness = material.iridescenceThicknessMaximum;
238
+ if ( material.iridescenceThicknessMap != - 1 ) {
239
+
240
+ vec3 uvPrime = material.iridescenceThicknessMapTransform * vec3( uv, 1 );
241
+ float iridescenceThicknessSampled = texture2D( textures, vec3( uvPrime.xy, material.iridescenceThicknessMap ) ).g;
242
+ iridescenceThickness = mix( material.iridescenceThicknessMinimum, material.iridescenceThicknessMaximum, iridescenceThicknessSampled );
243
+
244
+ }
245
+
246
+ iridescence = iridescenceThickness == 0.0 ? 0.0 : iridescence;
247
+
248
+ // specular color
249
+ vec3 specularColor = material.specularColor;
250
+ if ( material.specularColorMap != - 1 ) {
251
+
252
+ vec3 uvPrime = material.specularColorMapTransform * vec3( uv, 1 );
253
+ specularColor *= texture2D( textures, vec3( uvPrime.xy, material.specularColorMap ) ).rgb;
254
+
255
+ }
256
+
257
+ // specular intensity
258
+ float specularIntensity = material.specularIntensity;
259
+ if ( material.specularIntensityMap != - 1 ) {
260
+
261
+ vec3 uvPrime = material.specularIntensityMapTransform * vec3( uv, 1 );
262
+ specularIntensity *= texture2D( textures, vec3( uvPrime.xy, material.specularIntensityMap ) ).a;
263
+
264
+ }
265
+
266
+ surf.volumeParticle = false;
267
+
268
+ surf.faceNormal = faceNormal;
269
+ surf.normal = normal;
270
+
271
+ surf.metalness = metalness;
272
+ surf.color = albedo.rgb;
273
+ surf.emission = emission;
274
+
275
+ surf.ior = material.ior;
276
+ surf.transmission = transmission;
277
+ surf.thinFilm = material.thinFilm;
278
+ surf.attenuationColor = material.attenuationColor;
279
+ surf.attenuationDistance = material.attenuationDistance;
280
+
281
+ surf.clearcoatNormal = clearcoatNormal;
282
+ surf.clearcoat = clearcoat;
283
+
284
+ surf.sheen = material.sheen;
285
+ surf.sheenColor = sheenColor;
286
+
287
+ surf.iridescence = iridescence;
288
+ surf.iridescenceIor = material.iridescenceIor;
289
+ surf.iridescenceThickness = iridescenceThickness;
290
+
291
+ surf.specularColor = specularColor;
292
+ surf.specularIntensity = specularIntensity;
293
+
294
+ // apply perceptual roughness factor from gltf. sheen perceptual roughness is
295
+ // applied by its brdf function
296
+ // https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#microfacet-surfaces
297
+ surf.roughness = roughness * roughness;
298
+ surf.clearcoatRoughness = clearcoatRoughness * clearcoatRoughness;
299
+ surf.sheenRoughness = sheenRoughness;
300
+
301
+ // frontFace is used to determine transmissive properties and PDF. If no transmission is used
302
+ // then we can just always assume this is a front face.
303
+ surf.frontFace = side == 1.0 || transmission == 0.0;
304
+ surf.eta = material.thinFilm || surf.frontFace ? 1.0 / material.ior : material.ior;
305
+ surf.f0 = iorRatioToF0( surf.eta );
306
+
307
+ // Compute the filtered roughness value to use during specular reflection computations.
308
+ // The accumulated roughness value is scaled by a user setting and a "magic value" of 5.0.
309
+ // If we're exiting something transmissive then scale the factor down significantly so we can retain
310
+ // sharp internal reflections
311
+ surf.filteredRoughness = applyFilteredGlossy( surf.roughness, accumulatedRoughness );
312
+ surf.filteredClearcoatRoughness = applyFilteredGlossy( surf.clearcoatRoughness, accumulatedRoughness );
313
+
314
+ return HIT_SURFACE;
315
+
316
+ }
317
+ `;
@@ -0,0 +1,54 @@
1
+ export const traceSceneGLSL = /* glsl */`
2
+
3
+ #define NO_HIT 0
4
+ #define SURFACE_HIT 1
5
+ #define LIGHT_HIT 2
6
+ #define FOG_HIT 3
7
+
8
+ int traceScene(
9
+
10
+ vec3 rayOrigin, vec3 rayDirection,
11
+ BVH bvh, LightsInfo lights, Material fogMaterial,
12
+ out uvec4 faceIndices, out vec3 faceNormal, out vec3 barycoord, out float side, out float dist,
13
+ out LightSampleRecord lightSampleRec
14
+
15
+ ) {
16
+
17
+ bool hit = bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist );
18
+ bool lightHit = lightsClosestHit( lights.tex, lights.count, rayOrigin, rayDirection, lightSampleRec );
19
+
20
+ #if FEATURE_FOG
21
+
22
+ if ( fogMaterial.fogVolume ) {
23
+
24
+ float particleDist = intersectFogVolume( fogMaterial, sobol( 1 ) );
25
+ if ( particleDist + 1e-4 < dist && ( particleDist + 1e-4 < lightSampleRec.dist || ! lightHit ) ) {
26
+
27
+ side = 1.0;
28
+ faceNormal = normalize( - rayDirection );
29
+ dist = particleDist;
30
+ return FOG_HIT;
31
+
32
+ }
33
+
34
+ }
35
+
36
+ #endif
37
+
38
+ if ( lightHit && ( lightSampleRec.dist < dist || ! hit ) ) {
39
+
40
+ return LIGHT_HIT;
41
+
42
+ }
43
+
44
+ if ( hit ) {
45
+
46
+ return SURFACE_HIT;
47
+
48
+ }
49
+
50
+ return NO_HIT;
51
+
52
+ }
53
+
54
+ `;