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.
Files changed (76) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +1004 -981
  3. package/build/index.module.js +7413 -6902
  4. package/build/index.module.js.map +1 -1
  5. package/build/index.umd.cjs +7446 -6933
  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/detectors/CompatibilityDetector.js +38 -0
  14. package/src/detectors/MaterialCompileDetector.js +50 -0
  15. package/src/detectors/PrecisionDetector.js +85 -0
  16. package/src/detectors/PrecisionMaterial.js +160 -0
  17. package/src/index.js +40 -36
  18. package/src/materials/MaterialBase.js +56 -56
  19. package/src/materials/debug/GraphMaterial.js +243 -243
  20. package/src/materials/fullscreen/AlphaDisplayMaterial.js +50 -48
  21. package/src/materials/fullscreen/BlendMaterial.js +67 -67
  22. package/src/materials/fullscreen/DenoiseMaterial.js +142 -142
  23. package/src/materials/fullscreen/GradientMapMaterial.js +82 -0
  24. package/src/materials/pathtracing/LambertPathTracingMaterial.js +296 -296
  25. package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +118 -196
  26. package/src/materials/pathtracing/glsl/attenuateHit.glsl.js +177 -179
  27. package/src/materials/pathtracing/glsl/cameraUtils.glsl.js +84 -81
  28. package/src/materials/pathtracing/glsl/directLightContribution.glsl.js +93 -0
  29. package/src/materials/pathtracing/glsl/getSurfaceRecord.glsl.js +323 -317
  30. package/src/materials/pathtracing/glsl/renderStructs.glsl.js +50 -0
  31. package/src/materials/pathtracing/glsl/traceScene.glsl.js +52 -54
  32. package/src/materials/surface/AmbientOcclusionMaterial.js +207 -207
  33. package/src/materials/surface/FogVolumeMaterial.js +23 -23
  34. package/src/objects/EquirectCamera.js +13 -13
  35. package/src/objects/PhysicalCamera.js +42 -28
  36. package/src/objects/PhysicalSpotLight.js +25 -14
  37. package/src/objects/ShapedAreaLight.js +22 -12
  38. package/src/shader/bsdf/bsdfSampling.glsl.js +499 -490
  39. package/src/shader/bsdf/fog.glsl.js +22 -23
  40. package/src/shader/bsdf/ggx.glsl.js +102 -102
  41. package/src/shader/bsdf/iridescence.glsl.js +135 -135
  42. package/src/shader/bsdf/sheen.glsl.js +98 -98
  43. package/src/shader/common/arraySamplerTexelFetch.glsl.js +25 -25
  44. package/src/shader/common/bvhAnyHit.glsl.js +76 -76
  45. package/src/shader/common/fresnel.glsl.js +98 -98
  46. package/src/shader/common/intersectShapes.glsl.js +62 -62
  47. package/src/shader/common/math.glsl.js +81 -81
  48. package/src/shader/common/utils.glsl.js +116 -116
  49. package/src/shader/rand/pcg.glsl.js +57 -57
  50. package/src/shader/rand/sobol.glsl.js +256 -256
  51. package/src/shader/sampling/equirectSampling.glsl.js +62 -62
  52. package/src/shader/sampling/lightSampling.glsl.js +223 -223
  53. package/src/shader/sampling/shapeSampling.glsl.js +86 -86
  54. package/src/shader/structs/cameraStruct.glsl.js +13 -13
  55. package/src/shader/structs/equirectStruct.glsl.js +13 -14
  56. package/src/shader/structs/fogMaterialBvh.glsl.js +62 -62
  57. package/src/shader/structs/lightsStruct.glsl.js +78 -78
  58. package/src/shader/structs/materialStruct.glsl.js +207 -207
  59. package/src/textures/GradientEquirectTexture.js +35 -35
  60. package/src/textures/ProceduralEquirectTexture.js +75 -75
  61. package/src/uniforms/AttributesTextureArray.js +35 -35
  62. package/src/uniforms/EquirectHdrInfoUniform.js +269 -277
  63. package/src/uniforms/FloatAttributeTextureArray.js +169 -169
  64. package/src/uniforms/IESProfilesTexture.js +100 -100
  65. package/src/uniforms/LightsInfoUniformStruct.js +212 -212
  66. package/src/uniforms/MaterialsTexture.js +503 -503
  67. package/src/uniforms/PhysicalCameraUniform.js +36 -36
  68. package/src/uniforms/RenderTarget2DArray.js +97 -97
  69. package/src/uniforms/utils.js +30 -30
  70. package/src/utils/BlurredEnvMapGenerator.js +116 -116
  71. package/src/utils/GeometryPreparationUtils.js +214 -214
  72. package/src/utils/IESLoader.js +325 -325
  73. package/src/utils/SobolNumberMapGenerator.js +80 -80
  74. package/src/utils/UVUnwrapper.js +101 -101
  75. package/src/utils/macroify.js +9 -9
  76. package/src/workers/PathTracingSceneWorker.js +42 -42
@@ -1,296 +1,296 @@
1
- import { Matrix4, Color } from 'three';
2
- import { MaterialBase } from '../MaterialBase.js';
3
- import {
4
- MeshBVHUniformStruct, FloatVertexAttributeTexture, UIntVertexAttributeTexture,
5
- shaderStructs, shaderIntersectFunction,
6
- } from 'three-mesh-bvh';
7
-
8
- // uniforms
9
- import { MaterialStructArrayUniform } from '../uniforms/MaterialStructArrayUniform.js';
10
- import { RenderTarget2DArray } from '../../uniforms/RenderTarget2DArray.js';
11
-
12
- import { materialStructGLSL } from '../../shader/structs/materialStruct.glsl.js';
13
- import { shapeSamplingGLSL } from '../../shader/sampling/shapeSampling.glsl.js';
14
- import { pcgGLSL } from '../../shader/rand/pcg.glsl.js';
15
-
16
- export class LambertPathTracingMaterial extends MaterialBase {
17
-
18
- // three.js relies on this field to add env map functions and defines
19
- get envMap() {
20
-
21
- return this.environmentMap;
22
-
23
- }
24
-
25
- constructor( parameters ) {
26
-
27
- super( {
28
-
29
- transparent: true,
30
- depthWrite: false,
31
-
32
- defines: {
33
- BOUNCES: 3,
34
- MATERIAL_LENGTH: 0,
35
- GRADIENT_BG: 0,
36
- DISPLAY_FLOOR: 1,
37
- },
38
-
39
- uniforms: {
40
- bvh: { value: new MeshBVHUniformStruct() },
41
- normalAttribute: { value: new FloatVertexAttributeTexture() },
42
- tangentAttribute: { value: new FloatVertexAttributeTexture() },
43
- uvAttribute: { value: new FloatVertexAttributeTexture() },
44
- materialIndexAttribute: { value: new UIntVertexAttributeTexture() },
45
- materials: { value: new MaterialStructArrayUniform() },
46
- textures: { value: new RenderTarget2DArray().texture },
47
- cameraWorldMatrix: { value: new Matrix4() },
48
- invProjectionMatrix: { value: new Matrix4() },
49
- environmentBlur: { value: 0.2 },
50
- environmentIntensity: { value: 2.0 },
51
- environmentMap: { value: null },
52
- seed: { value: 0 },
53
- opacity: { value: 1 },
54
-
55
- gradientTop: { value: new Color( 0xbfd8ff ) },
56
- gradientBottom: { value: new Color( 0xffffff ) },
57
-
58
- bgGradientTop: { value: new Color( 0x111111 ) },
59
- bgGradientBottom: { value: new Color( 0x000000 ) },
60
-
61
- },
62
-
63
- vertexShader: /* glsl */`
64
-
65
- varying vec2 vUv;
66
- void main() {
67
-
68
- vec4 mvPosition = vec4( position, 1.0 );
69
- mvPosition = modelViewMatrix * mvPosition;
70
- gl_Position = projectionMatrix * mvPosition;
71
-
72
- vUv = uv;
73
-
74
- }
75
-
76
- `,
77
-
78
- fragmentShader: /* glsl */`
79
- #define RAY_OFFSET 1e-5
80
-
81
- precision highp isampler2D;
82
- precision highp usampler2D;
83
- precision highp sampler2DArray;
84
- vec4 envMapTexelToLinear( vec4 a ) { return a; }
85
- #include <common>
86
- #include <cube_uv_reflection_fragment>
87
-
88
- ${ shaderStructs }
89
- ${ shaderIntersectFunction }
90
-
91
- // uniform structs
92
- ${ materialStructGLSL }
93
-
94
- // rand
95
- ${ pcgGLSL }
96
-
97
- // common
98
- ${ shapeSamplingGLSL }
99
-
100
- #ifdef USE_ENVMAP
101
-
102
- uniform float environmentBlur;
103
- uniform sampler2D environmentMap;
104
-
105
- #else
106
-
107
- uniform vec3 gradientTop;
108
- uniform vec3 gradientBottom;
109
-
110
- #endif
111
-
112
- #if GRADIENT_BG
113
-
114
- uniform vec3 bgGradientTop;
115
- uniform vec3 bgGradientBottom;
116
-
117
- #endif
118
-
119
- uniform mat4 cameraWorldMatrix;
120
- uniform mat4 invProjectionMatrix;
121
- uniform sampler2D normalAttribute;
122
- uniform sampler2D tangentAttribute;
123
- uniform sampler2D uvAttribute;
124
- uniform usampler2D materialIndexAttribute;
125
- uniform BVH bvh;
126
- uniform float environmentIntensity;
127
- uniform int seed;
128
- uniform float opacity;
129
- uniform Material materials[ MATERIAL_LENGTH ];
130
- uniform sampler2DArray textures;
131
- varying vec2 vUv;
132
-
133
- void main() {
134
-
135
- rng_initialize( gl_FragCoord.xy, seed );
136
-
137
- // get [-1, 1] normalized device coordinates
138
- vec2 ndc = 2.0 * vUv - vec2( 1.0 );
139
- vec3 rayOrigin, rayDirection;
140
- ndcToCameraRay( ndc, cameraWorldMatrix, invProjectionMatrix, rayOrigin, rayDirection );
141
-
142
- // Lambertian render
143
- gl_FragColor = vec4( 0.0 );
144
-
145
- vec3 throughputColor = vec3( 1.0 );
146
-
147
- // hit results
148
- uvec4 faceIndices = uvec4( 0u );
149
- vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
150
- vec3 barycoord = vec3( 0.0 );
151
- float side = 1.0;
152
- float dist = 0.0;
153
- int i;
154
- for ( i = 0; i < BOUNCES; i ++ ) {
155
-
156
- if ( ! bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist ) ) {
157
-
158
- #if GRADIENT_BG
159
-
160
- if ( i == 0 ) {
161
-
162
- rayDirection = normalize( rayDirection );
163
- float value = ( rayDirection.y + 1.0 ) / 2.0;
164
-
165
- value = pow( value, 2.0 );
166
-
167
- gl_FragColor = vec4( mix( bgGradientBottom, bgGradientTop, value ), 1.0 );
168
- break;
169
-
170
- }
171
-
172
- #endif
173
-
174
- #ifdef USE_ENVMAP
175
-
176
- vec3 skyColor = textureCubeUV( environmentMap, rayDirection, environmentBlur ).rgb;
177
-
178
- #else
179
-
180
- rayDirection = normalize( rayDirection );
181
- float value = ( rayDirection.y + 1.0 ) / 2.0;
182
- vec3 skyColor = mix( gradientBottom, gradientTop, value );
183
-
184
- #endif
185
-
186
- gl_FragColor += vec4( skyColor * throughputColor * environmentIntensity, 1.0 );
187
-
188
- break;
189
-
190
- }
191
-
192
-
193
- uint materialIndex = uTexelFetch1D( materialIndexAttribute, faceIndices.x ).r;
194
- Material material = materials[ materialIndex ];
195
-
196
- if ( material.opacity < rand() ) {
197
-
198
- vec3 point = rayOrigin + rayDirection * dist;
199
- rayOrigin += rayDirection * dist - faceNormal * RAY_OFFSET;
200
- throughputColor *= mix( vec3( 1.0 ), material.color, 0.5 * material.opacity );
201
-
202
- i --;
203
- continue;
204
-
205
- }
206
-
207
- // fetch the interpolated smooth normal
208
- vec3 normal = normalize( textureSampleBarycoord(
209
- normalAttribute,
210
- barycoord,
211
- faceIndices.xyz
212
- ).xyz );
213
-
214
- vec2 uv = textureSampleBarycoord( uvAttribute, barycoord, faceIndices.xyz ).xy;
215
-
216
- // emission
217
- vec3 emission = material.emissiveIntensity * material.emissive;
218
- if ( material.emissiveMap != - 1 ) {
219
-
220
- emission *= texture2D( textures, vec3( uv, material.emissiveMap ) ).xyz;
221
-
222
- }
223
-
224
- gl_FragColor.rgb += throughputColor * emission * max( side, 0.0 );
225
-
226
- // 1 / PI attenuation for physically correct lambert model
227
- // https://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/
228
- throughputColor *= 1.0 / PI;
229
-
230
- // albedo
231
- throughputColor *= material.color;
232
- if ( material.map != - 1 ) {
233
-
234
- throughputColor *= texture2D( textures, vec3( uv, material.map ) ).xyz;
235
-
236
- }
237
-
238
- // normal
239
- if ( material.normalMap != - 1 ) {
240
-
241
- vec4 tangentSample = textureSampleBarycoord(
242
- tangentAttribute,
243
- barycoord,
244
- faceIndices.xyz
245
- );
246
-
247
- // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
248
- // resulting in NaNs and slow path tracing.
249
- if ( length( tangentSample.xyz ) > 0.0 ) {
250
-
251
- vec3 tangent = normalize( tangentSample.xyz );
252
- vec3 bitangent = normalize( cross( normal, tangent ) * tangentSample.w );
253
- mat3 vTBN = mat3( tangent, bitangent, normal );
254
-
255
- vec3 texNormal = texture2D( textures, vec3( uv, material.normalMap ) ).xyz * 2.0 - 1.0;
256
- texNormal.xy *= material.normalScale;
257
- normal = vTBN * texNormal;
258
-
259
- }
260
-
261
- }
262
-
263
- normal *= side;
264
-
265
- // adjust the hit point by the surface normal by a factor of some offset and the
266
- // maximum component-wise value of the current point to accommodate floating point
267
- // error as values increase.
268
- vec3 point = rayOrigin + rayDirection * dist;
269
- vec3 absPoint = abs( point );
270
- float maxPoint = max( absPoint.x, max( absPoint.y, absPoint.z ) );
271
- rayOrigin = point + faceNormal * ( maxPoint + 1.0 ) * RAY_OFFSET;
272
- rayDirection = sampleHemisphere( normal, rand2() );
273
-
274
- // if the surface normal is skewed such that the outgoing vector can wind up underneath
275
- // the triangle surface then just consider it absorbed.
276
- if ( dot( rayDirection, faceNormal ) < 0.0 ) {
277
-
278
- break;
279
-
280
- }
281
-
282
- }
283
-
284
- gl_FragColor.a = opacity;
285
-
286
- }
287
-
288
- `
289
-
290
- } );
291
-
292
- this.setValues( parameters );
293
-
294
- }
295
-
296
- }
1
+ import { Matrix4, Color } from 'three';
2
+ import { MaterialBase } from '../MaterialBase.js';
3
+ import {
4
+ MeshBVHUniformStruct, FloatVertexAttributeTexture, UIntVertexAttributeTexture,
5
+ shaderStructs, shaderIntersectFunction,
6
+ } from 'three-mesh-bvh';
7
+
8
+ // uniforms
9
+ import { MaterialStructArrayUniform } from '../uniforms/MaterialStructArrayUniform.js';
10
+ import { RenderTarget2DArray } from '../../uniforms/RenderTarget2DArray.js';
11
+
12
+ import { materialStructGLSL } from '../../shader/structs/materialStruct.glsl.js';
13
+ import { shapeSamplingGLSL } from '../../shader/sampling/shapeSampling.glsl.js';
14
+ import { pcgGLSL } from '../../shader/rand/pcg.glsl.js';
15
+
16
+ export class LambertPathTracingMaterial extends MaterialBase {
17
+
18
+ // three.js relies on this field to add env map functions and defines
19
+ get envMap() {
20
+
21
+ return this.environmentMap;
22
+
23
+ }
24
+
25
+ constructor( parameters ) {
26
+
27
+ super( {
28
+
29
+ transparent: true,
30
+ depthWrite: false,
31
+
32
+ defines: {
33
+ BOUNCES: 3,
34
+ MATERIAL_LENGTH: 0,
35
+ GRADIENT_BG: 0,
36
+ DISPLAY_FLOOR: 1,
37
+ },
38
+
39
+ uniforms: {
40
+ bvh: { value: new MeshBVHUniformStruct() },
41
+ normalAttribute: { value: new FloatVertexAttributeTexture() },
42
+ tangentAttribute: { value: new FloatVertexAttributeTexture() },
43
+ uvAttribute: { value: new FloatVertexAttributeTexture() },
44
+ materialIndexAttribute: { value: new UIntVertexAttributeTexture() },
45
+ materials: { value: new MaterialStructArrayUniform() },
46
+ textures: { value: new RenderTarget2DArray().texture },
47
+ cameraWorldMatrix: { value: new Matrix4() },
48
+ invProjectionMatrix: { value: new Matrix4() },
49
+ environmentBlur: { value: 0.2 },
50
+ environmentIntensity: { value: 2.0 },
51
+ environmentMap: { value: null },
52
+ seed: { value: 0 },
53
+ opacity: { value: 1 },
54
+
55
+ gradientTop: { value: new Color( 0xbfd8ff ) },
56
+ gradientBottom: { value: new Color( 0xffffff ) },
57
+
58
+ bgGradientTop: { value: new Color( 0x111111 ) },
59
+ bgGradientBottom: { value: new Color( 0x000000 ) },
60
+
61
+ },
62
+
63
+ vertexShader: /* glsl */`
64
+
65
+ varying vec2 vUv;
66
+ void main() {
67
+
68
+ vec4 mvPosition = vec4( position, 1.0 );
69
+ mvPosition = modelViewMatrix * mvPosition;
70
+ gl_Position = projectionMatrix * mvPosition;
71
+
72
+ vUv = uv;
73
+
74
+ }
75
+
76
+ `,
77
+
78
+ fragmentShader: /* glsl */`
79
+ #define RAY_OFFSET 1e-5
80
+
81
+ precision highp isampler2D;
82
+ precision highp usampler2D;
83
+ precision highp sampler2DArray;
84
+ vec4 envMapTexelToLinear( vec4 a ) { return a; }
85
+ #include <common>
86
+ #include <cube_uv_reflection_fragment>
87
+
88
+ ${ shaderStructs }
89
+ ${ shaderIntersectFunction }
90
+
91
+ // uniform structs
92
+ ${ materialStructGLSL }
93
+
94
+ // rand
95
+ ${ pcgGLSL }
96
+
97
+ // common
98
+ ${ shapeSamplingGLSL }
99
+
100
+ #ifdef USE_ENVMAP
101
+
102
+ uniform float environmentBlur;
103
+ uniform sampler2D environmentMap;
104
+
105
+ #else
106
+
107
+ uniform vec3 gradientTop;
108
+ uniform vec3 gradientBottom;
109
+
110
+ #endif
111
+
112
+ #if GRADIENT_BG
113
+
114
+ uniform vec3 bgGradientTop;
115
+ uniform vec3 bgGradientBottom;
116
+
117
+ #endif
118
+
119
+ uniform mat4 cameraWorldMatrix;
120
+ uniform mat4 invProjectionMatrix;
121
+ uniform sampler2D normalAttribute;
122
+ uniform sampler2D tangentAttribute;
123
+ uniform sampler2D uvAttribute;
124
+ uniform usampler2D materialIndexAttribute;
125
+ uniform BVH bvh;
126
+ uniform float environmentIntensity;
127
+ uniform int seed;
128
+ uniform float opacity;
129
+ uniform Material materials[ MATERIAL_LENGTH ];
130
+ uniform sampler2DArray textures;
131
+ varying vec2 vUv;
132
+
133
+ void main() {
134
+
135
+ rng_initialize( gl_FragCoord.xy, seed );
136
+
137
+ // get [-1, 1] normalized device coordinates
138
+ vec2 ndc = 2.0 * vUv - vec2( 1.0 );
139
+ vec3 rayOrigin, rayDirection;
140
+ ndcToCameraRay( ndc, cameraWorldMatrix, invProjectionMatrix, rayOrigin, rayDirection );
141
+
142
+ // Lambertian render
143
+ gl_FragColor = vec4( 0.0 );
144
+
145
+ vec3 throughputColor = vec3( 1.0 );
146
+
147
+ // hit results
148
+ uvec4 faceIndices = uvec4( 0u );
149
+ vec3 faceNormal = vec3( 0.0, 0.0, 1.0 );
150
+ vec3 barycoord = vec3( 0.0 );
151
+ float side = 1.0;
152
+ float dist = 0.0;
153
+ int i;
154
+ for ( i = 0; i < BOUNCES; i ++ ) {
155
+
156
+ if ( ! bvhIntersectFirstHit( bvh, rayOrigin, rayDirection, faceIndices, faceNormal, barycoord, side, dist ) ) {
157
+
158
+ #if GRADIENT_BG
159
+
160
+ if ( i == 0 ) {
161
+
162
+ rayDirection = normalize( rayDirection );
163
+ float value = ( rayDirection.y + 1.0 ) / 2.0;
164
+
165
+ value = pow( value, 2.0 );
166
+
167
+ gl_FragColor = vec4( mix( bgGradientBottom, bgGradientTop, value ), 1.0 );
168
+ break;
169
+
170
+ }
171
+
172
+ #endif
173
+
174
+ #ifdef USE_ENVMAP
175
+
176
+ vec3 skyColor = textureCubeUV( environmentMap, rayDirection, environmentBlur ).rgb;
177
+
178
+ #else
179
+
180
+ rayDirection = normalize( rayDirection );
181
+ float value = ( rayDirection.y + 1.0 ) / 2.0;
182
+ vec3 skyColor = mix( gradientBottom, gradientTop, value );
183
+
184
+ #endif
185
+
186
+ gl_FragColor += vec4( skyColor * throughputColor * environmentIntensity, 1.0 );
187
+
188
+ break;
189
+
190
+ }
191
+
192
+
193
+ uint materialIndex = uTexelFetch1D( materialIndexAttribute, faceIndices.x ).r;
194
+ Material material = materials[ materialIndex ];
195
+
196
+ if ( material.opacity < rand() ) {
197
+
198
+ vec3 point = rayOrigin + rayDirection * dist;
199
+ rayOrigin += rayDirection * dist - faceNormal * RAY_OFFSET;
200
+ throughputColor *= mix( vec3( 1.0 ), material.color, 0.5 * material.opacity );
201
+
202
+ i --;
203
+ continue;
204
+
205
+ }
206
+
207
+ // fetch the interpolated smooth normal
208
+ vec3 normal = normalize( textureSampleBarycoord(
209
+ normalAttribute,
210
+ barycoord,
211
+ faceIndices.xyz
212
+ ).xyz );
213
+
214
+ vec2 uv = textureSampleBarycoord( uvAttribute, barycoord, faceIndices.xyz ).xy;
215
+
216
+ // emission
217
+ vec3 emission = material.emissiveIntensity * material.emissive;
218
+ if ( material.emissiveMap != - 1 ) {
219
+
220
+ emission *= texture2D( textures, vec3( uv, material.emissiveMap ) ).xyz;
221
+
222
+ }
223
+
224
+ gl_FragColor.rgb += throughputColor * emission * max( side, 0.0 );
225
+
226
+ // 1 / PI attenuation for physically correct lambert model
227
+ // https://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/
228
+ throughputColor *= 1.0 / PI;
229
+
230
+ // albedo
231
+ throughputColor *= material.color;
232
+ if ( material.map != - 1 ) {
233
+
234
+ throughputColor *= texture2D( textures, vec3( uv, material.map ) ).xyz;
235
+
236
+ }
237
+
238
+ // normal
239
+ if ( material.normalMap != - 1 ) {
240
+
241
+ vec4 tangentSample = textureSampleBarycoord(
242
+ tangentAttribute,
243
+ barycoord,
244
+ faceIndices.xyz
245
+ );
246
+
247
+ // some provided tangents can be malformed (0, 0, 0) causing the normal to be degenerate
248
+ // resulting in NaNs and slow path tracing.
249
+ if ( length( tangentSample.xyz ) > 0.0 ) {
250
+
251
+ vec3 tangent = normalize( tangentSample.xyz );
252
+ vec3 bitangent = normalize( cross( normal, tangent ) * tangentSample.w );
253
+ mat3 vTBN = mat3( tangent, bitangent, normal );
254
+
255
+ vec3 texNormal = texture2D( textures, vec3( uv, material.normalMap ) ).xyz * 2.0 - 1.0;
256
+ texNormal.xy *= material.normalScale;
257
+ normal = vTBN * texNormal;
258
+
259
+ }
260
+
261
+ }
262
+
263
+ normal *= side;
264
+
265
+ // adjust the hit point by the surface normal by a factor of some offset and the
266
+ // maximum component-wise value of the current point to accommodate floating point
267
+ // error as values increase.
268
+ vec3 point = rayOrigin + rayDirection * dist;
269
+ vec3 absPoint = abs( point );
270
+ float maxPoint = max( absPoint.x, max( absPoint.y, absPoint.z ) );
271
+ rayOrigin = point + faceNormal * ( maxPoint + 1.0 ) * RAY_OFFSET;
272
+ rayDirection = sampleHemisphere( normal, rand2() );
273
+
274
+ // if the surface normal is skewed such that the outgoing vector can wind up underneath
275
+ // the triangle surface then just consider it absorbed.
276
+ if ( dot( rayDirection, faceNormal ) < 0.0 ) {
277
+
278
+ break;
279
+
280
+ }
281
+
282
+ }
283
+
284
+ gl_FragColor.a = opacity;
285
+
286
+ }
287
+
288
+ `
289
+
290
+ } );
291
+
292
+ this.setValues( parameters );
293
+
294
+ }
295
+
296
+ }