three-gpu-pathtracer 0.0.23 → 0.0.25

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 (83) hide show
  1. package/README.md +53 -528
  2. package/build/index.module.js +319 -66
  3. package/build/index.module.js.map +1 -1
  4. package/build/index.umd.cjs +318 -64
  5. package/build/index.umd.cjs.map +1 -1
  6. package/package.json +35 -18
  7. package/src/core/PathTracingSceneGenerator.js +21 -2
  8. package/src/core/WebGLPathTracer.js +16 -7
  9. package/src/core/utils/mergeGeometries.js +14 -1
  10. package/src/core/utils/sceneUpdateUtils.js +8 -12
  11. package/src/detectors/PrecisionMaterial.js +9 -9
  12. package/src/index.d.ts +2 -1
  13. package/src/index.js +1 -0
  14. package/src/materials/pathtracing/PhysicalPathTracingMaterial.js +2 -1
  15. package/src/materials/pathtracing/glsl/attenuate_hit_function.glsl.js +2 -1
  16. package/src/materials/pathtracing/glsl/camera_util_functions.glsl.js +1 -1
  17. package/src/materials/pathtracing/glsl/get_surface_record_function.glsl.js +2 -1
  18. package/src/materials/surface/AmbientOcclusionMaterial.js +2 -0
  19. package/src/objects/PhysicalSpotLight.js +2 -0
  20. package/src/shader/bsdf/bsdf_functions.glsl.js +0 -1
  21. package/src/shader/bvh/inside_fog_volume_function.glsl.js +1 -1
  22. package/src/shader/structs/material_struct.glsl.js +3 -1
  23. package/src/textures/BlueNoiseTexture.js +6 -6
  24. package/src/textures/ProceduralEquirectTexture.js +8 -7
  25. package/src/textures/turquinMetal.png +0 -0
  26. package/src/uniforms/EquirectHdrInfoUniform.js +9 -4
  27. package/src/uniforms/FloatAttributeTextureArray.js +11 -11
  28. package/src/uniforms/MaterialsTexture.js +13 -10
  29. package/src/webgpu/API.md +762 -0
  30. package/src/webgpu/AtlasTexture.js +471 -0
  31. package/src/webgpu/BlurredEnvMapGenerator.js +129 -0
  32. package/src/webgpu/EquirectBackgroundInfo.js +97 -0
  33. package/src/webgpu/EquirectHdrInfoNode.js +151 -0
  34. package/src/webgpu/LightsInfoNode.js +224 -0
  35. package/src/webgpu/MegaKernelPathTracer.js +277 -0
  36. package/src/webgpu/PathTracerBackend.js +216 -0
  37. package/src/webgpu/TurquinTexture.js +169 -0
  38. package/src/webgpu/WaveFrontPathTracer.js +586 -0
  39. package/src/webgpu/WebGPUPathTracer.js +1302 -0
  40. package/src/webgpu/compute/ComputeKernel.js +92 -0
  41. package/src/webgpu/compute/CopyBufferKernel.js +40 -0
  42. package/src/webgpu/compute/PathTracerMegaKernel.js +470 -0
  43. package/src/webgpu/compute/SampleDebugKernel.js +51 -0
  44. package/src/webgpu/compute/TallySampleCountsKernel.js +111 -0
  45. package/src/webgpu/compute/ZeroOutBufferKernel.js +35 -0
  46. package/src/webgpu/compute/ZeroOutKernel.js +31 -0
  47. package/src/webgpu/compute/wavefront/LogicKernel.js +349 -0
  48. package/src/webgpu/compute/wavefront/MaterialKernel.js +371 -0
  49. package/src/webgpu/compute/wavefront/PopulatePixelIndicesKernel.js +72 -0
  50. package/src/webgpu/compute/wavefront/QueueLengthToDispatchKernel.js +38 -0
  51. package/src/webgpu/compute/wavefront/ResetSlotsKernel.js +66 -0
  52. package/src/webgpu/compute/wavefront/TraceRayKernel.js +71 -0
  53. package/src/webgpu/compute/wavefront/TraceShadowRayKernel.js +67 -0
  54. package/src/webgpu/compute/wavefront/structs.js +155 -0
  55. package/src/webgpu/constants.js +62 -0
  56. package/src/webgpu/denoise/OIDNDenoiser.js +431 -0
  57. package/src/webgpu/index.d.ts +176 -0
  58. package/src/webgpu/index.js +11 -0
  59. package/src/webgpu/materials/GltfCompliantMaterial.js +608 -0
  60. package/src/webgpu/materials/GraphMaterial.js +331 -0
  61. package/src/webgpu/materials/PathtracingMaterial.js +89 -0
  62. package/src/webgpu/materials/RenderToScreenMaterial.js +150 -0
  63. package/src/webgpu/materials/debug/AtlasDebugMaterial.js +41 -0
  64. package/src/webgpu/materials/debug/SampleDensityMaterial.js +61 -0
  65. package/src/webgpu/nodes/PathtracerBVHComputeData.js +1037 -0
  66. package/src/webgpu/nodes/debugBounds.wgsl.js +228 -0
  67. package/src/webgpu/nodes/eon.wgsl.js +262 -0
  68. package/src/webgpu/nodes/ggx.wgsl.js +190 -0
  69. package/src/webgpu/nodes/lights.wgsl.js +203 -0
  70. package/src/webgpu/nodes/material.wgsl.js +990 -0
  71. package/src/webgpu/nodes/rand/bluedither.wgsl.js +92 -0
  72. package/src/webgpu/nodes/rand/pcg.wgsl.js +81 -0
  73. package/src/webgpu/nodes/rand/sobol.wgsl.js +287 -0
  74. package/src/webgpu/nodes/random.wgsl.js +20 -0
  75. package/src/webgpu/nodes/reset.wgsl.js +21 -0
  76. package/src/webgpu/nodes/sampling.wgsl.js +193 -0
  77. package/src/webgpu/nodes/sheen.wgsl.js +148 -0
  78. package/src/webgpu/nodes/structs.wgsl.js +272 -0
  79. package/src/webgpu/nodes/utils.wgsl.js +366 -0
  80. package/src/webgpu/shims/ArrayCameraShim.js +74 -0
  81. package/src/webgpu/shims/EquirectCameraShim.js +37 -0
  82. package/src/webgpu/shims/PhysicalCameraShim.js +151 -0
  83. package/src/webgpu/upscale/FSRUpscaler.js +108 -0
@@ -0,0 +1,203 @@
1
+ import { wgslFn } from 'three/tsl';
2
+ import { constants, lightStruct, lightRecordStruct } from './structs.wgsl.js';
3
+
4
+ // Light type tags matching LightsInfoUniformStruct's packing. The environment is treated as an
5
+ // additional light kind so env + analytic lights share one NEE path.
6
+ export const RECT_AREA_LIGHT_TYPE = 0;
7
+ export const CIRC_AREA_LIGHT_TYPE = 1;
8
+ export const SPOT_LIGHT_TYPE = 2;
9
+ export const DIR_LIGHT_TYPE = 3;
10
+ export const POINT_LIGHT_TYPE = 4;
11
+ export const ENVIRONMENT_LIGHT_TYPE = 5;
12
+ export const LIGHT_FAR_DISTANCE = 1e30;
13
+
14
+ // tolerance for comparing a shadow hit distance to the sampled light distance
15
+ export const LIGHT_EPSILON = 1e-5;
16
+
17
+ // light kinds that are also bsdf-sampled and so take MIS-weighted NEE - punctual lights take full weight
18
+ export const isMISWeightLightFn = wgslFn( /* wgsl */ `
19
+
20
+ fn isMISWeightLight( lightType: i32 ) -> bool {
21
+
22
+ return lightType == ${ ENVIRONMENT_LIGHT_TYPE } || lightType == ${ CIRC_AREA_LIGHT_TYPE } || lightType == ${ RECT_AREA_LIGHT_TYPE };
23
+
24
+ }
25
+
26
+ ` );
27
+
28
+ export const getSpotAttenuationFn = wgslFn( /* wgsl */ `
29
+
30
+ fn getSpotAttenuation( coneCosine: f32, penumbraCosine: f32, angleCosine: f32 ) -> f32 {
31
+
32
+ return smoothstep( coneCosine, penumbraCosine, angleCosine );
33
+
34
+ }
35
+
36
+ ` );
37
+
38
+ export const getDistanceAttenuationFn = wgslFn( /* wgsl */ `
39
+
40
+ fn getDistanceAttenuation( lightDistance: f32, cutoffDistance: f32, decayExponent: f32 ) -> f32 {
41
+
42
+ // based upon Frostbite 3 Moving to Physically-based Rendering
43
+ // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
44
+ var distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), EPSILON );
45
+ if ( cutoffDistance > 0.0 ) {
46
+
47
+ let window = clamp( 1.0 - pow( lightDistance / cutoffDistance, 4.0 ), 0.0, 1.0 );
48
+ distanceFalloff *= window * window;
49
+
50
+ }
51
+
52
+ return distanceFalloff;
53
+
54
+ }
55
+
56
+ `, [ constants ] );
57
+
58
+ // Ray/plane intersection constrained to a rectangle centered at "center" spanned by u, v.
59
+ // Returns the hit distance along the ray, or a negative value when there is no hit.
60
+ export const intersectsRectangleFn = wgslFn( /* wgsl */ `
61
+
62
+ fn intersectsRectangle( center: vec3f, normal: vec3f, u: vec3f, v: vec3f, rayOrigin: vec3f, rayDirection: vec3f ) -> f32 {
63
+
64
+ let t = dot( center - rayOrigin, normal ) / dot( rayDirection, normal );
65
+ if ( t > EPSILON ) {
66
+
67
+ let p = rayOrigin + rayDirection * t;
68
+ let vi = p - center;
69
+
70
+ let a1 = dot( u, vi );
71
+ if ( abs( a1 ) <= 0.5 ) {
72
+
73
+ let a2 = dot( v, vi );
74
+ if ( abs( a2 ) <= 0.5 ) {
75
+
76
+ return t;
77
+
78
+ }
79
+
80
+ }
81
+
82
+ }
83
+
84
+ return - 1.0;
85
+
86
+ }
87
+
88
+ `, [ constants ] );
89
+
90
+ // Ray/plane intersection constrained to a circle centered at "position" spanned by u, v.
91
+ // Returns the hit distance along the ray, or a negative value when there is no hit.
92
+ export const intersectsCircleFn = wgslFn( /* wgsl */ `
93
+
94
+ fn intersectsCircle( position: vec3f, normal: vec3f, u: vec3f, v: vec3f, rayOrigin: vec3f, rayDirection: vec3f ) -> f32 {
95
+
96
+ let t = dot( position - rayOrigin, normal ) / dot( rayDirection, normal );
97
+ if ( t > EPSILON ) {
98
+
99
+ let hit = rayOrigin + rayDirection * t;
100
+ let vi = hit - position;
101
+
102
+ let a1 = dot( u, vi );
103
+ let a2 = dot( v, vi );
104
+ if ( length( vec2f( a1, a2 ) ) <= 0.5 ) {
105
+
106
+ return t;
107
+
108
+ }
109
+
110
+ }
111
+
112
+ return - 1.0;
113
+
114
+ }
115
+
116
+ `, [ constants ] );
117
+
118
+ // Samples a random point on a rectangular or circular area light and forms the LightRecord.
119
+ export const randomAreaLightSampleFn = wgslFn( /* wgsl */ `
120
+
121
+ fn randomAreaLightSample( light: Light, rayOrigin: vec3f, ruv: vec2f ) -> LightRecord {
122
+
123
+ var randomPos = vec3f( 0.0 );
124
+ if ( light.lightType == ${ RECT_AREA_LIGHT_TYPE } ) {
125
+
126
+ randomPos = light.position + light.u * ( ruv.x - 0.5 ) + light.v * ( ruv.y - 0.5 );
127
+
128
+ } else if ( light.lightType == ${ CIRC_AREA_LIGHT_TYPE } ) {
129
+
130
+ let r = 0.5 * sqrt( ruv.x );
131
+ let theta = ruv.y * 2.0 * PI;
132
+ randomPos = light.position + light.u * ( r * cos( theta ) ) + light.v * ( r * sin( theta ) );
133
+
134
+ }
135
+
136
+ let toLight = randomPos - rayOrigin;
137
+ let lightDistSq = dot( toLight, toLight );
138
+ let dist = sqrt( lightDistSq );
139
+ let direction = toLight / dist;
140
+ let lightNormal = normalize( cross( light.u, light.v ) );
141
+
142
+ var lightRec: LightRecord;
143
+ lightRec.lightType = light.lightType;
144
+ lightRec.emission = light.color * light.intensity;
145
+ lightRec.dist = dist;
146
+ lightRec.direction = direction;
147
+
148
+ // points behind or edge-on to the light receive no contribution
149
+ let cosTheta = dot( direction, lightNormal );
150
+ if ( cosTheta <= 0.0 ) {
151
+
152
+ lightRec.pdf = 0.0;
153
+
154
+ } else {
155
+
156
+ lightRec.pdf = lightDistSq / ( light.area * cosTheta );
157
+
158
+ }
159
+
160
+ return lightRec;
161
+
162
+ }
163
+
164
+ `, [ lightStruct, lightRecordStruct, constants ] );
165
+
166
+ // Samples the disc of a spot light with distance falloff. Angular ( cone or IES ) attenuation is applied by the caller.
167
+ export const randomSpotLightSampleFn = wgslFn( /* wgsl */ `
168
+
169
+ fn randomSpotLightSample( light: Light, rayOrigin: vec3f, ruv: vec2f ) -> LightRecord {
170
+
171
+ let radius = light.radius * sqrt( ruv.x );
172
+ let theta = ruv.y * 2.0 * PI;
173
+ let x = radius * cos( theta );
174
+ let y = radius * sin( theta );
175
+
176
+ let u = light.u;
177
+ let v = light.v;
178
+ let normal = normalize( cross( u, v ) );
179
+
180
+ let angle = acos( light.coneCos );
181
+ let angleTan = tan( angle );
182
+ let startDistance = light.radius / max( angleTan, EPSILON );
183
+
184
+ let randomPos = light.position - normal * startDistance + u * x + v * y;
185
+ let toLight = randomPos - rayOrigin;
186
+ let lightDistSq = dot( toLight, toLight );
187
+ let dist = sqrt( lightDistSq );
188
+
189
+ let direction = toLight / max( dist, EPSILON );
190
+ let distanceAttenuation = getDistanceAttenuation( dist, light.distance, light.decay );
191
+
192
+ var lightRec: LightRecord;
193
+ lightRec.lightType = light.lightType;
194
+ lightRec.dist = dist;
195
+ lightRec.direction = direction;
196
+ lightRec.emission = light.color * light.intensity * distanceAttenuation;
197
+ lightRec.pdf = 1.0;
198
+
199
+ return lightRec;
200
+
201
+ }
202
+
203
+ `, [ lightStruct, lightRecordStruct, constants, getDistanceAttenuationFn ] );