three-gpu-pathtracer 0.0.1 → 0.0.4

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 (36) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +678 -386
  3. package/build/index.module.js +3166 -1690
  4. package/build/index.module.js.map +1 -1
  5. package/build/index.umd.cjs +3176 -1692
  6. package/build/index.umd.cjs.map +1 -1
  7. package/package.json +60 -57
  8. package/src/core/DynamicPathTracingSceneGenerator.js +106 -0
  9. package/src/core/MaterialReducer.js +256 -256
  10. package/src/core/PathTracingRenderer.js +125 -28
  11. package/src/core/PathTracingSceneGenerator.js +52 -46
  12. package/src/core/PhysicalCamera.js +28 -0
  13. package/src/index.js +25 -21
  14. package/src/materials/AlphaDisplayMaterial.js +48 -0
  15. package/src/materials/AmbientOcclusionMaterial.js +197 -197
  16. package/src/materials/BlendMaterial.js +67 -0
  17. package/src/materials/LambertPathTracingMaterial.js +285 -285
  18. package/src/materials/MaterialBase.js +56 -56
  19. package/src/materials/PhysicalPathTracingMaterial.js +684 -370
  20. package/src/shader/shaderEnvMapSampling.js +67 -0
  21. package/src/shader/shaderGGXFunctions.js +108 -107
  22. package/src/shader/shaderMaterialSampling.js +345 -333
  23. package/src/shader/shaderStructs.js +131 -30
  24. package/src/shader/shaderUtils.js +246 -140
  25. package/src/uniforms/EquirectHdrInfoUniform.js +263 -0
  26. package/src/uniforms/MaterialsTexture.js +251 -0
  27. package/src/uniforms/PhysicalCameraUniform.js +36 -0
  28. package/src/uniforms/RenderTarget2DArray.js +93 -80
  29. package/src/utils/BlurredEnvMapGenerator.js +113 -0
  30. package/src/utils/GeometryPreparationUtils.js +194 -172
  31. package/src/utils/UVUnwrapper.js +101 -101
  32. package/src/workers/PathTracingSceneWorker.js +40 -0
  33. package/src/uniforms/EquirectPdfUniform.js +0 -132
  34. package/src/uniforms/MaterialStructArrayUniform.js +0 -18
  35. package/src/uniforms/MaterialStructUniform.js +0 -94
  36. package/src/viewers/PathTracingViewer.js +0 -259
@@ -0,0 +1,67 @@
1
+ export const shaderEnvMapSampling = /* glsl */`
2
+
3
+ vec3 sampleEquirectEnvMapColor( vec3 direction, sampler2D map ) {
4
+
5
+ return texture2D( map, equirectDirectionToUv( direction ) ).rgb;
6
+
7
+ }
8
+
9
+ float envMapDirectionPdf( vec3 direction ) {
10
+
11
+ vec2 uv = equirectDirectionToUv( direction );
12
+ float theta = uv.y * PI;
13
+ float sinTheta = sin( theta );
14
+ if ( sinTheta == 0.0 ) {
15
+
16
+ return 0.0;
17
+
18
+ }
19
+
20
+ return 1.0 / ( 2.0 * PI * PI * sinTheta );
21
+
22
+ }
23
+
24
+ float envMapSample( vec3 direction, EquirectHdrInfo info, out vec3 color ) {
25
+
26
+ vec2 uv = equirectDirectionToUv( direction );
27
+ color = texture2D( info.map, uv ).rgb;
28
+
29
+ float totalSum = texture2D( info.totalSum, vec2( 0.0 ) ).r;
30
+ float lum = colorToLuminance( color );
31
+ ivec2 resolution = textureSize( info.map, 0 );
32
+ float pdf = lum / totalSum;
33
+
34
+ return float( resolution.x * resolution.y ) * pdf * envMapDirectionPdf( direction );
35
+
36
+ }
37
+
38
+ float randomEnvMapSample( EquirectHdrInfo info, out vec3 color, out vec3 direction ) {
39
+
40
+ // sample env map cdf
41
+ vec2 r = rand2();
42
+ float v = texture2D( info.marginalWeights, vec2( r.x, 0.0 ) ).x;
43
+ float u = texture2D( info.conditionalWeights, vec2( r.y, v ) ).x;
44
+ vec2 uv = vec2( u, v );
45
+
46
+ vec3 derivedDirection = equirectUvToDirection( uv );
47
+ direction = derivedDirection;
48
+ color = texture2D( info.map, uv ).rgb;
49
+
50
+ float totalSum = texture2D( info.totalSum, vec2( 0.0 ) ).r;
51
+ float lum = colorToLuminance( color );
52
+ ivec2 resolution = textureSize( info.map, 0 );
53
+ float pdf = lum / totalSum;
54
+
55
+ return float( resolution.x * resolution.y ) * pdf * envMapDirectionPdf( direction );
56
+
57
+ }
58
+
59
+ float misHeuristic( float a, float b ) {
60
+
61
+ float aa = a * a;
62
+ float bb = a * b;
63
+ return aa / ( bb + aa );
64
+
65
+ }
66
+
67
+ `;
@@ -1,107 +1,108 @@
1
- export const shaderGGXFunctions = /* glsl */`
2
- // The GGX functions provide sampling and distribution information for normals as output so
3
- // in order to get probability of scatter direction the half vector must be computed and provided.
4
- // [0] https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf
5
- // [1] https://hal.archives-ouvertes.fr/hal-01509746/document
6
- // [2] http://jcgt.org/published/0007/04/01/
7
- // [4] http://jcgt.org/published/0003/02/03/
8
-
9
- // trowbridge-reitz === GGX === GTR
10
-
11
- vec3 ggxDirection( vec3 incidentDir, float roughnessX, float roughnessY, float random1, float random2 ) {
12
-
13
- // TODO: try GGXVNDF implementation from reference [2], here. Needs to update ggxDistribution
14
- // function below, as well
15
-
16
- // Implementation from reference [1]
17
- // stretch view
18
- vec3 V = normalize( vec3( roughnessX * incidentDir.x, roughnessY * incidentDir.y, incidentDir.z ) );
19
-
20
- // orthonormal basis
21
- vec3 T1 = ( V.z < 0.9999 ) ? normalize( cross( V, vec3( 0.0, 0.0, 1.0 ) ) ) : vec3( 1.0, 0.0, 0.0 );
22
- vec3 T2 = cross( T1, V );
23
-
24
- // sample point with polar coordinates (r, phi)
25
- float a = 1.0 / ( 1.0 + V.z );
26
- float r = sqrt( random1 );
27
- float phi = ( random2 < a ) ? random2 / a * PI : PI + ( random2 - a ) / ( 1.0 - a ) * PI;
28
- float P1 = r * cos( phi );
29
- float P2 = r * sin( phi ) * ( ( random2 < a ) ? 1.0 : V.z );
30
-
31
- // compute normal
32
- vec3 N = P1 * T1 + P2 * T2 + V * sqrt( max( 0.0, 1.0 - P1 * P1 - P2 * P2 ) );
33
-
34
- // unstretch
35
- N = normalize( vec3( roughnessX * N.x, roughnessY * N.y, max( 0.0, N.z ) ) );
36
-
37
- return N;
38
-
39
- }
40
-
41
- // Below are PDF and related functions for use in a Monte Carlo path tracer
42
- // as specified in Appendix B of the following paper
43
- // See equation (2) from reference [2]
44
- float ggxLamda( float theta, float roughness ) {
45
-
46
- float tanTheta = tan( theta );
47
- float tanTheta2 = tanTheta * tanTheta;
48
- float alpha2 = roughness * roughness;
49
-
50
- float numerator = - 1.0 + sqrt( 1.0 + alpha2 * tanTheta2 );
51
- return numerator / 2.0;
52
-
53
- }
54
-
55
- // See equation (2) from reference [2]
56
- float ggxShadowMaskG1( float theta, float roughness ) {
57
-
58
- return 1.0 / ( 1.0 + ggxLamda( theta, roughness ) );
59
-
60
- }
61
-
62
- // See equation (125) from reference [4]
63
- float ggxShadowMaskG2( vec3 wi, vec3 wo, float roughness ) {
64
-
65
- float incidentTheta = acos( wi.z );
66
- float scatterTheta = acos( wo.z );
67
- return 1.0 / ( 1.0 + ggxLamda( incidentTheta, roughness ) + ggxLamda( scatterTheta, roughness ) );
68
-
69
- }
70
-
71
- float ggxDistribution( vec3 halfVector, float roughness ) {
72
-
73
- // See equation (33) from reference [0]
74
- float a2 = roughness * roughness;
75
- float cosTheta = halfVector.z;
76
- float cosTheta4 = pow( cosTheta, 4.0 );
77
-
78
- if ( cosTheta == 0.0 ) return 0.0;
79
-
80
- float theta = acos( halfVector.z );
81
- float tanTheta = tan( theta );
82
- float tanTheta2 = pow( tanTheta, 2.0 );
83
-
84
- float denom = PI * cosTheta4 * pow( a2 + tanTheta2, 2.0 );
85
- return a2 / denom;
86
-
87
- // See equation (1) from reference [2]
88
- // const { x, y, z } = halfVector;
89
- // const a2 = roughness * roughness;
90
- // const mult = x * x / a2 + y * y / a2 + z * z;
91
- // const mult2 = mult * mult;
92
-
93
- // return 1.0 / Math.PI * a2 * mult2;
94
-
95
- }
96
-
97
- // See equation (3) from reference [2]
98
- float ggxPDF( vec3 wi, vec3 halfVector, float roughness ) {
99
-
100
- float incidentTheta = acos( wi.z );
101
- float D = ggxDistribution( halfVector, roughness );
102
- float G1 = ggxShadowMaskG1( incidentTheta, roughness );
103
-
104
- return D * G1 * max( 0.0, dot( wi, halfVector ) ) / wi.z;
105
-
106
- }
107
- `;
1
+ export const shaderGGXFunctions = /* glsl */`
2
+ // The GGX functions provide sampling and distribution information for normals as output so
3
+ // in order to get probability of scatter direction the half vector must be computed and provided.
4
+ // [0] https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf
5
+ // [1] https://hal.archives-ouvertes.fr/hal-01509746/document
6
+ // [2] http://jcgt.org/published/0007/04/01/
7
+ // [4] http://jcgt.org/published/0003/02/03/
8
+
9
+ // trowbridge-reitz === GGX === GTR
10
+
11
+ vec3 ggxDirection( vec3 incidentDir, float roughnessX, float roughnessY, float random1, float random2 ) {
12
+
13
+ // TODO: try GGXVNDF implementation from reference [2], here. Needs to update ggxDistribution
14
+ // function below, as well
15
+
16
+ // Implementation from reference [1]
17
+ // stretch view
18
+ vec3 V = normalize( vec3( roughnessX * incidentDir.x, roughnessY * incidentDir.y, incidentDir.z ) );
19
+
20
+ // orthonormal basis
21
+ vec3 T1 = ( V.z < 0.9999 ) ? normalize( cross( V, vec3( 0.0, 0.0, 1.0 ) ) ) : vec3( 1.0, 0.0, 0.0 );
22
+ vec3 T2 = cross( T1, V );
23
+
24
+ // sample point with polar coordinates (r, phi)
25
+ float a = 1.0 / ( 1.0 + V.z );
26
+ float r = sqrt( random1 );
27
+ float phi = ( random2 < a ) ? random2 / a * PI : PI + ( random2 - a ) / ( 1.0 - a ) * PI;
28
+ float P1 = r * cos( phi );
29
+ float P2 = r * sin( phi ) * ( ( random2 < a ) ? 1.0 : V.z );
30
+
31
+ // compute normal
32
+ vec3 N = P1 * T1 + P2 * T2 + V * sqrt( max( 0.0, 1.0 - P1 * P1 - P2 * P2 ) );
33
+
34
+ // unstretch
35
+ N = normalize( vec3( roughnessX * N.x, roughnessY * N.y, max( 0.0, N.z ) ) );
36
+
37
+ return N;
38
+
39
+ }
40
+
41
+ // Below are PDF and related functions for use in a Monte Carlo path tracer
42
+ // as specified in Appendix B of the following paper
43
+ // See equation (2) from reference [2]
44
+ float ggxLamda( float theta, float roughness ) {
45
+
46
+ float tanTheta = tan( theta );
47
+ float tanTheta2 = tanTheta * tanTheta;
48
+ float alpha2 = roughness * roughness;
49
+
50
+ float numerator = - 1.0 + sqrt( 1.0 + alpha2 * tanTheta2 );
51
+ return numerator / 2.0;
52
+
53
+ }
54
+
55
+ // See equation (2) from reference [2]
56
+ float ggxShadowMaskG1( float theta, float roughness ) {
57
+
58
+ return 1.0 / ( 1.0 + ggxLamda( theta, roughness ) );
59
+
60
+ }
61
+
62
+ // See equation (125) from reference [4]
63
+ float ggxShadowMaskG2( vec3 wi, vec3 wo, float roughness ) {
64
+
65
+ float incidentTheta = acos( wi.z );
66
+ float scatterTheta = acos( wo.z );
67
+ return 1.0 / ( 1.0 + ggxLamda( incidentTheta, roughness ) + ggxLamda( scatterTheta, roughness ) );
68
+
69
+ }
70
+
71
+ float ggxDistribution( vec3 halfVector, float roughness ) {
72
+
73
+ // See equation (33) from reference [0]
74
+ float a2 = roughness * roughness;
75
+ a2 = max( EPSILON, a2 );
76
+ float cosTheta = halfVector.z;
77
+ float cosTheta4 = pow( cosTheta, 4.0 );
78
+
79
+ if ( cosTheta == 0.0 ) return 0.0;
80
+
81
+ float theta = acosSafe( halfVector.z );
82
+ float tanTheta = tan( theta );
83
+ float tanTheta2 = pow( tanTheta, 2.0 );
84
+
85
+ float denom = PI * cosTheta4 * pow( a2 + tanTheta2, 2.0 );
86
+ return ( a2 / denom );
87
+
88
+ // See equation (1) from reference [2]
89
+ // const { x, y, z } = halfVector;
90
+ // const a2 = roughness * roughness;
91
+ // const mult = x * x / a2 + y * y / a2 + z * z;
92
+ // const mult2 = mult * mult;
93
+
94
+ // return 1.0 / Math.PI * a2 * mult2;
95
+
96
+ }
97
+
98
+ // See equation (3) from reference [2]
99
+ float ggxPDF( vec3 wi, vec3 halfVector, float roughness ) {
100
+
101
+ float incidentTheta = acos( wi.z );
102
+ float D = ggxDistribution( halfVector, roughness );
103
+ float G1 = ggxShadowMaskG1( incidentTheta, roughness );
104
+
105
+ return D * G1 * max( 0.0, dot( wi, halfVector ) ) / wi.z;
106
+
107
+ }
108
+ `;