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
|
@@ -1,490 +1,499 @@
|
|
|
1
|
-
import { ggxGLSL } from './ggx.glsl.js';
|
|
2
|
-
import { sheenGLSL } from './sheen.glsl.js';
|
|
3
|
-
import { iridescenceGLSL } from './iridescence.glsl.js';
|
|
4
|
-
|
|
5
|
-
/*
|
|
6
|
-
wi : incident vector or light vector (pointing toward the light)
|
|
7
|
-
wo : outgoing vector or view vector (pointing towards the camera)
|
|
8
|
-
wh : computed half vector from wo and wi
|
|
9
|
-
Eval : Get the color and pdf for a direction
|
|
10
|
-
Sample : Get the direction, color, and pdf for a sample
|
|
11
|
-
eta : Greek character used to denote the "ratio of ior"
|
|
12
|
-
f0 : Amount of light reflected when looking at a surface head on - "fresnel 0"
|
|
13
|
-
f90 : Amount of light reflected at grazing angles
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export const bsdfSamplingGLSL = /* glsl */`
|
|
17
|
-
|
|
18
|
-
struct SurfaceRecord {
|
|
19
|
-
|
|
20
|
-
// surface type
|
|
21
|
-
bool volumeParticle;
|
|
22
|
-
|
|
23
|
-
// geometry
|
|
24
|
-
vec3 faceNormal;
|
|
25
|
-
bool frontFace;
|
|
26
|
-
vec3 normal;
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
float
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
float
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
float
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
float
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
float
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
vec3
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
${
|
|
79
|
-
${
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
float
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
float
|
|
90
|
-
float
|
|
91
|
-
float
|
|
92
|
-
float
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
lightDirection
|
|
106
|
-
lightDirection
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
float
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
float
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
vec3
|
|
124
|
-
vec3
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
float
|
|
133
|
-
float
|
|
134
|
-
float
|
|
135
|
-
float
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
float
|
|
166
|
-
|
|
167
|
-
bool
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
float
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
float
|
|
223
|
-
|
|
224
|
-
vec3
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
float
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
float
|
|
245
|
-
float
|
|
246
|
-
float
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
//
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
float
|
|
277
|
-
float
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
float
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
color
|
|
285
|
-
color *=
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
float
|
|
299
|
-
float
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
float
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
diffuseWeight
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
float
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
float
|
|
326
|
-
float
|
|
327
|
-
float
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
color
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
+
|
|
372
|
-
+
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
sampleRec
|
|
414
|
-
sampleRec.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
float
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
cdf[
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
wi =
|
|
472
|
-
clearcoatWi = normalize( clearcoatInvBasis * normalize( normalBasis * wi ) );
|
|
473
|
-
|
|
474
|
-
} else if ( r <= cdf[
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
1
|
+
import { ggxGLSL } from './ggx.glsl.js';
|
|
2
|
+
import { sheenGLSL } from './sheen.glsl.js';
|
|
3
|
+
import { iridescenceGLSL } from './iridescence.glsl.js';
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
wi : incident vector or light vector (pointing toward the light)
|
|
7
|
+
wo : outgoing vector or view vector (pointing towards the camera)
|
|
8
|
+
wh : computed half vector from wo and wi
|
|
9
|
+
Eval : Get the color and pdf for a direction
|
|
10
|
+
Sample : Get the direction, color, and pdf for a sample
|
|
11
|
+
eta : Greek character used to denote the "ratio of ior"
|
|
12
|
+
f0 : Amount of light reflected when looking at a surface head on - "fresnel 0"
|
|
13
|
+
f90 : Amount of light reflected at grazing angles
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const bsdfSamplingGLSL = /* glsl */`
|
|
17
|
+
|
|
18
|
+
struct SurfaceRecord {
|
|
19
|
+
|
|
20
|
+
// surface type
|
|
21
|
+
bool volumeParticle;
|
|
22
|
+
|
|
23
|
+
// geometry
|
|
24
|
+
vec3 faceNormal;
|
|
25
|
+
bool frontFace;
|
|
26
|
+
vec3 normal;
|
|
27
|
+
mat3 normalBasis;
|
|
28
|
+
mat3 normalInvBasis;
|
|
29
|
+
|
|
30
|
+
// cached properties
|
|
31
|
+
float eta;
|
|
32
|
+
float f0;
|
|
33
|
+
|
|
34
|
+
// material
|
|
35
|
+
float roughness;
|
|
36
|
+
float filteredRoughness;
|
|
37
|
+
float metalness;
|
|
38
|
+
vec3 color;
|
|
39
|
+
vec3 emission;
|
|
40
|
+
|
|
41
|
+
// transmission
|
|
42
|
+
float ior;
|
|
43
|
+
float transmission;
|
|
44
|
+
bool thinFilm;
|
|
45
|
+
vec3 attenuationColor;
|
|
46
|
+
float attenuationDistance;
|
|
47
|
+
|
|
48
|
+
// clearcoat
|
|
49
|
+
vec3 clearcoatNormal;
|
|
50
|
+
mat3 clearcoatBasis;
|
|
51
|
+
mat3 clearcoatInvBasis;
|
|
52
|
+
float clearcoat;
|
|
53
|
+
float clearcoatRoughness;
|
|
54
|
+
float filteredClearcoatRoughness;
|
|
55
|
+
|
|
56
|
+
// sheen
|
|
57
|
+
float sheen;
|
|
58
|
+
vec3 sheenColor;
|
|
59
|
+
float sheenRoughness;
|
|
60
|
+
|
|
61
|
+
// iridescence
|
|
62
|
+
float iridescence;
|
|
63
|
+
float iridescenceIor;
|
|
64
|
+
float iridescenceThickness;
|
|
65
|
+
|
|
66
|
+
// specular
|
|
67
|
+
vec3 specularColor;
|
|
68
|
+
float specularIntensity;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
struct ScatterRecord {
|
|
72
|
+
float specularPdf;
|
|
73
|
+
float pdf;
|
|
74
|
+
vec3 direction;
|
|
75
|
+
vec3 color;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
${ ggxGLSL }
|
|
79
|
+
${ sheenGLSL }
|
|
80
|
+
${ iridescenceGLSL }
|
|
81
|
+
|
|
82
|
+
// diffuse
|
|
83
|
+
float diffuseEval( vec3 wo, vec3 wi, vec3 wh, SurfaceRecord surf, out vec3 color ) {
|
|
84
|
+
|
|
85
|
+
// https://schuttejoe.github.io/post/disneybsdf/
|
|
86
|
+
float fl = schlickFresnel( wi.z, 0.0 );
|
|
87
|
+
float fv = schlickFresnel( wo.z, 0.0 );
|
|
88
|
+
|
|
89
|
+
float metalFactor = ( 1.0 - surf.metalness );
|
|
90
|
+
float transFactor = ( 1.0 - surf.transmission );
|
|
91
|
+
float rr = 0.5 + 2.0 * surf.roughness * fl * fl;
|
|
92
|
+
float retro = rr * ( fl + fv + fl * fv * ( rr - 1.0f ) );
|
|
93
|
+
float lambert = ( 1.0f - 0.5f * fl ) * ( 1.0f - 0.5f * fv );
|
|
94
|
+
|
|
95
|
+
// TODO: subsurface approx?
|
|
96
|
+
|
|
97
|
+
float F = evaluateFresnelWeight( dot( wo, wh ), surf.eta, surf.f0 );
|
|
98
|
+
color = ( 1.0 - F ) * transFactor * metalFactor * wi.z * surf.color * ( retro + lambert ) / PI;
|
|
99
|
+
return wi.z / PI;
|
|
100
|
+
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
vec3 diffuseDirection( vec3 wo, SurfaceRecord surf ) {
|
|
104
|
+
|
|
105
|
+
vec3 lightDirection = sampleSphere( sobol2( 11 ) );
|
|
106
|
+
lightDirection.z += 1.0;
|
|
107
|
+
lightDirection = normalize( lightDirection );
|
|
108
|
+
|
|
109
|
+
return lightDirection;
|
|
110
|
+
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// specular
|
|
114
|
+
float specularEval( vec3 wo, vec3 wi, vec3 wh, SurfaceRecord surf, out vec3 color ) {
|
|
115
|
+
|
|
116
|
+
// if roughness is set to 0 then D === NaN which results in black pixels
|
|
117
|
+
float metalness = surf.metalness;
|
|
118
|
+
float roughness = surf.filteredRoughness;
|
|
119
|
+
|
|
120
|
+
float eta = surf.eta;
|
|
121
|
+
float f0 = surf.f0;
|
|
122
|
+
|
|
123
|
+
vec3 f0Color = mix( f0 * surf.specularColor * surf.specularIntensity, surf.color, surf.metalness );
|
|
124
|
+
vec3 f90Color = vec3( mix( surf.specularIntensity, 1.0, surf.metalness ) );
|
|
125
|
+
vec3 F = evaluateFresnel( dot( wo, wh ), eta, f0Color, f90Color );
|
|
126
|
+
|
|
127
|
+
vec3 iridescenceF = evalIridescence( 1.0, surf.iridescenceIor, dot( wi, wh ), surf.iridescenceThickness, f0Color );
|
|
128
|
+
F = mix( F, iridescenceF, surf.iridescence );
|
|
129
|
+
|
|
130
|
+
// PDF
|
|
131
|
+
// See 14.1.1 Microfacet BxDFs in https://www.pbr-book.org/
|
|
132
|
+
float incidentTheta = acos( wo.z );
|
|
133
|
+
float G = ggxShadowMaskG2( wi, wo, roughness );
|
|
134
|
+
float D = ggxDistribution( wh, roughness );
|
|
135
|
+
float G1 = ggxShadowMaskG1( incidentTheta, roughness );
|
|
136
|
+
float ggxPdf = D * G1 * max( 0.0, abs( dot( wo, wh ) ) ) / abs ( wo.z );
|
|
137
|
+
|
|
138
|
+
color = wi.z * F * G * D / ( 4.0 * abs( wi.z * wo.z ) );
|
|
139
|
+
return ggxPdf / ( 4.0 * dot( wo, wh ) );
|
|
140
|
+
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
vec3 specularDirection( vec3 wo, SurfaceRecord surf ) {
|
|
144
|
+
|
|
145
|
+
// sample ggx vndf distribution which gives a new normal
|
|
146
|
+
float roughness = surf.filteredRoughness;
|
|
147
|
+
vec3 halfVector = ggxDirection(
|
|
148
|
+
wo,
|
|
149
|
+
vec2( roughness ),
|
|
150
|
+
sobol2( 12 )
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// apply to new ray by reflecting off the new normal
|
|
154
|
+
return - reflect( wo, halfVector );
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
// transmission
|
|
160
|
+
/*
|
|
161
|
+
float transmissionEval( vec3 wo, vec3 wi, vec3 wh, SurfaceRecord surf, out vec3 color ) {
|
|
162
|
+
|
|
163
|
+
// See section 4.2 in https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf
|
|
164
|
+
|
|
165
|
+
float filteredRoughness = surf.filteredRoughness;
|
|
166
|
+
float eta = surf.eta;
|
|
167
|
+
bool frontFace = surf.frontFace;
|
|
168
|
+
bool thinFilm = surf.thinFilm;
|
|
169
|
+
|
|
170
|
+
color = surf.transmission * surf.color;
|
|
171
|
+
|
|
172
|
+
float denom = pow( eta * dot( wi, wh ) + dot( wo, wh ), 2.0 );
|
|
173
|
+
return ggxPDF( wo, wh, filteredRoughness ) / denom;
|
|
174
|
+
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
vec3 transmissionDirection( vec3 wo, SurfaceRecord surf ) {
|
|
178
|
+
|
|
179
|
+
float filteredRoughness = surf.filteredRoughness;
|
|
180
|
+
float eta = surf.eta;
|
|
181
|
+
bool frontFace = surf.frontFace;
|
|
182
|
+
|
|
183
|
+
// sample ggx vndf distribution which gives a new normal
|
|
184
|
+
vec3 halfVector = ggxDirection(
|
|
185
|
+
wo,
|
|
186
|
+
vec2( filteredRoughness ),
|
|
187
|
+
sobol2( 13 )
|
|
188
|
+
);
|
|
189
|
+
|
|
190
|
+
vec3 lightDirection = refract( normalize( - wo ), halfVector, eta );
|
|
191
|
+
if ( surf.thinFilm ) {
|
|
192
|
+
|
|
193
|
+
lightDirection = - refract( normalize( - lightDirection ), - vec3( 0.0, 0.0, 1.0 ), 1.0 / eta );
|
|
194
|
+
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return normalize( lightDirection );
|
|
198
|
+
|
|
199
|
+
}
|
|
200
|
+
*/
|
|
201
|
+
|
|
202
|
+
// TODO: This is just using a basic cosine-weighted specular distribution with an
|
|
203
|
+
// incorrect PDF value at the moment. Update it to correctly use a GGX distribution
|
|
204
|
+
float transmissionEval( vec3 wo, vec3 wi, vec3 wh, SurfaceRecord surf, out vec3 color ) {
|
|
205
|
+
|
|
206
|
+
color = surf.transmission * surf.color;
|
|
207
|
+
|
|
208
|
+
// PDF
|
|
209
|
+
float F = evaluateFresnelWeight( dot( wo, wh ), surf.eta, surf.f0 );
|
|
210
|
+
if ( F >= 1.0 ) {
|
|
211
|
+
|
|
212
|
+
return 0.0;
|
|
213
|
+
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return 1.0 / ( 1.0 - F );
|
|
217
|
+
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
vec3 transmissionDirection( vec3 wo, SurfaceRecord surf ) {
|
|
221
|
+
|
|
222
|
+
float roughness = surf.filteredRoughness;
|
|
223
|
+
float eta = surf.eta;
|
|
224
|
+
vec3 halfVector = normalize( vec3( 0.0, 0.0, 1.0 ) + sampleSphere( sobol2( 13 ) ) * roughness );
|
|
225
|
+
vec3 lightDirection = refract( normalize( - wo ), halfVector, eta );
|
|
226
|
+
|
|
227
|
+
if ( surf.thinFilm ) {
|
|
228
|
+
|
|
229
|
+
lightDirection = - refract( normalize( - lightDirection ), - vec3( 0.0, 0.0, 1.0 ), 1.0 / eta );
|
|
230
|
+
|
|
231
|
+
}
|
|
232
|
+
return normalize( lightDirection );
|
|
233
|
+
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// clearcoat
|
|
237
|
+
float clearcoatEval( vec3 wo, vec3 wi, vec3 wh, SurfaceRecord surf, inout vec3 color ) {
|
|
238
|
+
|
|
239
|
+
float ior = 1.5;
|
|
240
|
+
float f0 = iorRatioToF0( ior );
|
|
241
|
+
bool frontFace = surf.frontFace;
|
|
242
|
+
float roughness = surf.filteredClearcoatRoughness;
|
|
243
|
+
|
|
244
|
+
float eta = frontFace ? 1.0 / ior : ior;
|
|
245
|
+
float G = ggxShadowMaskG2( wi, wo, roughness );
|
|
246
|
+
float D = ggxDistribution( wh, roughness );
|
|
247
|
+
float F = schlickFresnel( dot( wi, wh ), f0 );
|
|
248
|
+
|
|
249
|
+
float fClearcoat = F * D * G / ( 4.0 * abs( wi.z * wo.z ) );
|
|
250
|
+
color = color * ( 1.0 - surf.clearcoat * F ) + fClearcoat * surf.clearcoat * wi.z;
|
|
251
|
+
|
|
252
|
+
// PDF
|
|
253
|
+
// See equation (27) in http://jcgt.org/published/0003/02/03/
|
|
254
|
+
return ggxPDF( wo, wh, roughness ) / ( 4.0 * dot( wi, wh ) );
|
|
255
|
+
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
vec3 clearcoatDirection( vec3 wo, SurfaceRecord surf ) {
|
|
259
|
+
|
|
260
|
+
// sample ggx vndf distribution which gives a new normal
|
|
261
|
+
float roughness = surf.filteredClearcoatRoughness;
|
|
262
|
+
vec3 halfVector = ggxDirection(
|
|
263
|
+
wo,
|
|
264
|
+
vec2( roughness ),
|
|
265
|
+
sobol2( 14 )
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// apply to new ray by reflecting off the new normal
|
|
269
|
+
return - reflect( wo, halfVector );
|
|
270
|
+
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// sheen
|
|
274
|
+
vec3 sheenColor( vec3 wo, vec3 wi, vec3 wh, SurfaceRecord surf ) {
|
|
275
|
+
|
|
276
|
+
float cosThetaO = saturateCos( wo.z );
|
|
277
|
+
float cosThetaI = saturateCos( wi.z );
|
|
278
|
+
float cosThetaH = wh.z;
|
|
279
|
+
|
|
280
|
+
float D = velvetD( cosThetaH, surf.sheenRoughness );
|
|
281
|
+
float G = velvetG( cosThetaO, cosThetaI, surf.sheenRoughness );
|
|
282
|
+
|
|
283
|
+
// See equation (1) in http://www.aconty.com/pdf/s2017_pbs_imageworks_sheen.pdf
|
|
284
|
+
vec3 color = surf.sheenColor;
|
|
285
|
+
color *= D * G / ( 4.0 * abs( cosThetaO * cosThetaI ) );
|
|
286
|
+
color *= wi.z;
|
|
287
|
+
|
|
288
|
+
return color;
|
|
289
|
+
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// bsdf
|
|
293
|
+
void getLobeWeights(
|
|
294
|
+
vec3 wo, vec3 wi, vec3 wh, vec3 clearcoatWo, SurfaceRecord surf,
|
|
295
|
+
out float diffuseWeight, out float specularWeight, out float transmissionWeight, out float clearcoatWeight
|
|
296
|
+
) {
|
|
297
|
+
|
|
298
|
+
float metalness = surf.metalness;
|
|
299
|
+
float transmission = surf.transmission;
|
|
300
|
+
float fEstimate = evaluateFresnelWeight( dot( wo, wh ), surf.eta, surf.f0 );
|
|
301
|
+
|
|
302
|
+
float transSpecularProb = mix( max( 0.25, fEstimate ), 1.0, metalness );
|
|
303
|
+
float diffSpecularProb = 0.5 + 0.5 * metalness;
|
|
304
|
+
|
|
305
|
+
diffuseWeight = ( 1.0 - transmission ) * ( 1.0 - diffSpecularProb );
|
|
306
|
+
specularWeight = transmission * transSpecularProb + ( 1.0 - transmission ) * diffSpecularProb;
|
|
307
|
+
transmissionWeight = transmission * ( 1.0 - transSpecularProb );
|
|
308
|
+
clearcoatWeight = surf.clearcoat * schlickFresnel( clearcoatWo.z, 0.04 );
|
|
309
|
+
|
|
310
|
+
float totalWeight = diffuseWeight + specularWeight + transmissionWeight + clearcoatWeight;
|
|
311
|
+
diffuseWeight /= totalWeight;
|
|
312
|
+
specularWeight /= totalWeight;
|
|
313
|
+
transmissionWeight /= totalWeight;
|
|
314
|
+
clearcoatWeight /= totalWeight;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
float bsdfEval(
|
|
318
|
+
vec3 wo, vec3 clearcoatWo, vec3 wi, vec3 clearcoatWi, SurfaceRecord surf,
|
|
319
|
+
float diffuseWeight, float specularWeight, float transmissionWeight, float clearcoatWeight, out float specularPdf, out vec3 color
|
|
320
|
+
) {
|
|
321
|
+
|
|
322
|
+
float metalness = surf.metalness;
|
|
323
|
+
float transmission = surf.transmission;
|
|
324
|
+
|
|
325
|
+
float spdf = 0.0;
|
|
326
|
+
float dpdf = 0.0;
|
|
327
|
+
float tpdf = 0.0;
|
|
328
|
+
float cpdf = 0.0;
|
|
329
|
+
color = vec3( 0.0 );
|
|
330
|
+
|
|
331
|
+
vec3 halfVector = getHalfVector( wi, wo, surf.eta );
|
|
332
|
+
|
|
333
|
+
// diffuse
|
|
334
|
+
if ( diffuseWeight > 0.0 && wi.z > 0.0 ) {
|
|
335
|
+
|
|
336
|
+
dpdf = diffuseEval( wo, wi, halfVector, surf, color );
|
|
337
|
+
color *= 1.0 - surf.transmission;
|
|
338
|
+
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// ggx specular
|
|
342
|
+
if ( specularWeight > 0.0 && wi.z > 0.0 ) {
|
|
343
|
+
|
|
344
|
+
vec3 outColor;
|
|
345
|
+
spdf = specularEval( wo, wi, getHalfVector( wi, wo ), surf, outColor );
|
|
346
|
+
color += outColor;
|
|
347
|
+
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// transmission
|
|
351
|
+
if ( transmissionWeight > 0.0 && wi.z < 0.0 ) {
|
|
352
|
+
|
|
353
|
+
tpdf = transmissionEval( wo, wi, halfVector, surf, color );
|
|
354
|
+
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// sheen
|
|
358
|
+
color *= mix( 1.0, sheenAlbedoScaling( wo, wi, surf ), surf.sheen );
|
|
359
|
+
color += sheenColor( wo, wi, halfVector, surf ) * surf.sheen;
|
|
360
|
+
|
|
361
|
+
// clearcoat
|
|
362
|
+
if ( clearcoatWi.z >= 0.0 && clearcoatWeight > 0.0 ) {
|
|
363
|
+
|
|
364
|
+
vec3 clearcoatHalfVector = getHalfVector( clearcoatWo, clearcoatWi );
|
|
365
|
+
cpdf = clearcoatEval( clearcoatWo, clearcoatWi, clearcoatHalfVector, surf, color );
|
|
366
|
+
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
float pdf =
|
|
370
|
+
dpdf * diffuseWeight
|
|
371
|
+
+ spdf * specularWeight
|
|
372
|
+
+ tpdf * transmissionWeight
|
|
373
|
+
+ cpdf * clearcoatWeight;
|
|
374
|
+
|
|
375
|
+
// retrieve specular rays for the shadows flag
|
|
376
|
+
specularPdf = spdf * specularWeight + cpdf * clearcoatWeight;
|
|
377
|
+
|
|
378
|
+
return pdf;
|
|
379
|
+
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
float bsdfResult( vec3 worldWo, vec3 worldWi, SurfaceRecord surf, out vec3 color ) {
|
|
383
|
+
|
|
384
|
+
if ( surf.volumeParticle ) {
|
|
385
|
+
|
|
386
|
+
color = surf.color / ( 4.0 * PI );
|
|
387
|
+
return 1.0 / ( 4.0 * PI );
|
|
388
|
+
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
vec3 wo = normalize( surf.normalInvBasis * worldWo );
|
|
392
|
+
vec3 wi = normalize( surf.normalInvBasis * worldWi );
|
|
393
|
+
|
|
394
|
+
vec3 clearcoatWo = normalize( surf.clearcoatInvBasis * worldWo );
|
|
395
|
+
vec3 clearcoatWi = normalize( surf.clearcoatInvBasis * worldWi );
|
|
396
|
+
|
|
397
|
+
vec3 wh = getHalfVector( wo, wi, surf.eta );
|
|
398
|
+
float diffuseWeight;
|
|
399
|
+
float specularWeight;
|
|
400
|
+
float transmissionWeight;
|
|
401
|
+
float clearcoatWeight;
|
|
402
|
+
getLobeWeights( wo, wi, wh, clearcoatWo, surf, diffuseWeight, specularWeight, transmissionWeight, clearcoatWeight );
|
|
403
|
+
|
|
404
|
+
float specularPdf;
|
|
405
|
+
return bsdfEval( wo, clearcoatWo, wi, clearcoatWi, surf, diffuseWeight, specularWeight, transmissionWeight, clearcoatWeight, specularPdf, color );
|
|
406
|
+
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
ScatterRecord bsdfSample( vec3 worldWo, SurfaceRecord surf ) {
|
|
410
|
+
|
|
411
|
+
if ( surf.volumeParticle ) {
|
|
412
|
+
|
|
413
|
+
ScatterRecord sampleRec;
|
|
414
|
+
sampleRec.specularPdf = 0.0;
|
|
415
|
+
sampleRec.pdf = 1.0 / ( 4.0 * PI );
|
|
416
|
+
sampleRec.direction = sampleSphere( sobol2( 16 ) );
|
|
417
|
+
sampleRec.color = surf.color / ( 4.0 * PI );
|
|
418
|
+
return sampleRec;
|
|
419
|
+
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
vec3 wo = normalize( surf.normalInvBasis * worldWo );
|
|
423
|
+
vec3 clearcoatWo = normalize( surf.clearcoatInvBasis * worldWo );
|
|
424
|
+
mat3 normalBasis = surf.normalBasis;
|
|
425
|
+
mat3 invBasis = surf.normalInvBasis;
|
|
426
|
+
mat3 clearcoatNormalBasis = surf.clearcoatBasis;
|
|
427
|
+
mat3 clearcoatInvBasis = surf.clearcoatInvBasis;
|
|
428
|
+
|
|
429
|
+
float diffuseWeight;
|
|
430
|
+
float specularWeight;
|
|
431
|
+
float transmissionWeight;
|
|
432
|
+
float clearcoatWeight;
|
|
433
|
+
// using normal and basically-reflected ray since we don't have proper half vector here
|
|
434
|
+
getLobeWeights( wo, wo, vec3( 0, 0, 1 ), clearcoatWo, surf, diffuseWeight, specularWeight, transmissionWeight, clearcoatWeight );
|
|
435
|
+
|
|
436
|
+
float pdf[4];
|
|
437
|
+
pdf[0] = diffuseWeight;
|
|
438
|
+
pdf[1] = specularWeight;
|
|
439
|
+
pdf[2] = transmissionWeight;
|
|
440
|
+
pdf[3] = clearcoatWeight;
|
|
441
|
+
|
|
442
|
+
float cdf[4];
|
|
443
|
+
cdf[0] = pdf[0];
|
|
444
|
+
cdf[1] = pdf[1] + cdf[0];
|
|
445
|
+
cdf[2] = pdf[2] + cdf[1];
|
|
446
|
+
cdf[3] = pdf[3] + cdf[2];
|
|
447
|
+
|
|
448
|
+
if( cdf[3] != 0.0 ) {
|
|
449
|
+
|
|
450
|
+
float invMaxCdf = 1.0 / cdf[3];
|
|
451
|
+
cdf[0] *= invMaxCdf;
|
|
452
|
+
cdf[1] *= invMaxCdf;
|
|
453
|
+
cdf[2] *= invMaxCdf;
|
|
454
|
+
cdf[3] *= invMaxCdf;
|
|
455
|
+
|
|
456
|
+
} else {
|
|
457
|
+
|
|
458
|
+
cdf[0] = 1.0;
|
|
459
|
+
cdf[1] = 0.0;
|
|
460
|
+
cdf[2] = 0.0;
|
|
461
|
+
cdf[3] = 0.0;
|
|
462
|
+
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
vec3 wi;
|
|
466
|
+
vec3 clearcoatWi;
|
|
467
|
+
|
|
468
|
+
float r = sobol( 15 );
|
|
469
|
+
if ( r <= cdf[0] ) { // diffuse
|
|
470
|
+
|
|
471
|
+
wi = diffuseDirection( wo, surf );
|
|
472
|
+
clearcoatWi = normalize( clearcoatInvBasis * normalize( normalBasis * wi ) );
|
|
473
|
+
|
|
474
|
+
} else if ( r <= cdf[1] ) { // specular
|
|
475
|
+
|
|
476
|
+
wi = specularDirection( wo, surf );
|
|
477
|
+
clearcoatWi = normalize( clearcoatInvBasis * normalize( normalBasis * wi ) );
|
|
478
|
+
|
|
479
|
+
} else if ( r <= cdf[2] ) { // transmission / refraction
|
|
480
|
+
|
|
481
|
+
wi = transmissionDirection( wo, surf );
|
|
482
|
+
clearcoatWi = normalize( clearcoatInvBasis * normalize( normalBasis * wi ) );
|
|
483
|
+
|
|
484
|
+
} else if ( r <= cdf[3] ) { // clearcoat
|
|
485
|
+
|
|
486
|
+
clearcoatWi = clearcoatDirection( clearcoatWo, surf );
|
|
487
|
+
wi = normalize( invBasis * normalize( clearcoatNormalBasis * clearcoatWi ) );
|
|
488
|
+
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
ScatterRecord result;
|
|
492
|
+
result.pdf = bsdfEval( wo, clearcoatWo, wi, clearcoatWi, surf, diffuseWeight, specularWeight, transmissionWeight, clearcoatWeight, result.specularPdf, result.color );
|
|
493
|
+
result.direction = normalize( surf.normalBasis * wi );
|
|
494
|
+
|
|
495
|
+
return result;
|
|
496
|
+
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
`;
|