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