three-gpu-pathtracer 0.0.3 → 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.
package/README.md CHANGED
@@ -1,660 +1,678 @@
1
- # three-gpu-pathtracer
2
-
3
- [![npm version](https://img.shields.io/npm/v/three-gpu-pathtracer.svg?style=flat-square)](https://www.npmjs.com/package/three-gpu-pathtracer)
4
- [![lgtm code quality](https://img.shields.io/lgtm/grade/javascript/g/gkjohnson/three-gpu-pathtracer.svg?style=flat-square&label=code-quality)](https://lgtm.com/projects/g/gkjohnson/three-gpu-pathtracer/)
5
- [![build](https://img.shields.io/github/workflow/status/gkjohnson/three-gpu-pathtracer/Node.js%20CI?style=flat-square&label=build)](https://github.com/gkjohnson/three-gpu-pathtracer/actions)
6
- [![github](https://flat.badgen.net/badge/icon/github?icon=github&label)](https://github.com/gkjohnson/three-gpu-pathtracer/)
7
- [![twitter](https://flat.badgen.net/twitter/follow/garrettkjohnson)](https://twitter.com/garrettkjohnson)
8
- [![sponsors](https://img.shields.io/github/sponsors/gkjohnson?style=flat-square&color=1da1f2)](https://github.com/sponsors/gkjohnson/)
9
-
10
- ![](https://user-images.githubusercontent.com/734200/162287477-96696b18-890b-4c1b-8a73-d662e577cc48.png)
11
-
12
- Path tracing project using [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) and WebGL 2 to accelerate high quality, physically based rendering on the GPU. Features include support for GGX surface model, material information, textures, normal maps, emission, environment maps, tiled rendering, and more!
13
-
14
- _More features and capabilities in progress!_
15
-
16
- # Examples
17
-
18
- **Beauty Demos**
19
-
20
- [Physically Based Materials](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/index.html)
21
-
22
- [Lego Models](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/lego.html)
23
-
24
- [Interior Scene](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/interior.html)
25
-
26
- [Depth of Field](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/depthOfField.html)
27
-
28
- **Features**
29
-
30
- [Skinned Geometry Support](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/skinnedMesh.html)
31
-
32
- [Morph Target Support](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/skinnedMesh.html#morphtarget)
33
-
34
- **Test Scenes**
35
-
36
- [Material Test Orb](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/materialBall.html)
37
-
38
- [Transmission Preset Orb](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/materialBall.html#transmission)
39
-
40
- **Light Baking**
41
-
42
- [Ambient Occlusion Material](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/aoRender.html)
43
-
44
- # Use
45
-
46
- **Basic Renderer**
47
-
48
- ```js
49
- import * as THREE from 'three';
50
- import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
51
- import {
52
- PathTracingSceneGenerator,
53
- PathTracingRenderer,
54
- PhysicalPathTracingMaterial,
55
- } from 'three-gpu-pathtracer';
56
-
57
- // init scene, renderer, camera, controls, etc
58
-
59
- // initialize the path tracing material and renderer
60
- const ptMaterial = new PhysicalPathTracingMaterial();
61
- const ptRenderer = new PathTracingRenderer( renderer );
62
- ptRenderer.setSize( window.innerWidth, window.innerHeight );
63
- ptRenderer.camera = camera;
64
- ptRenderer.material = ptMaterial;
65
-
66
- // if rendering transparent background
67
- ptRenderer.alpha = true;
68
-
69
- // init quad for rendering to the canvas
70
- const fsQuad = new FullScreenQuad( new THREE.MeshBasicMaterial( {
71
- map: ptRenderer.target.texture,
72
-
73
- // if rendering transparent background
74
- blending: THREE.CustomBlending,
75
- } ) );
76
-
77
- // ensure scene matrices are up to date
78
- scene.updateMatrixWorld();
79
-
80
- // initialize the scene and update the material properties with the bvh, materials, etc
81
- const generator = new PathTracingSceneGenerator();
82
- const { bvh, textures, materials } = generator.generate( scene );
83
-
84
- // update bvh and geometry attribute textures
85
- ptMaterial.bvh.updateFrom( bvh );
86
- ptMaterial.normalAttribute.updateFrom( geometry.attributes.normal );
87
- ptMaterial.tangentAttribute.updateFrom( geometry.attributes.tangent );
88
- ptMaterial.uvAttribute.updateFrom( geometry.attributes.uv );
89
-
90
- // update materials and texture arrays
91
- ptMaterial.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
92
- ptMaterial.textures.setTextures( renderer, 2048, 2048, textures );
93
- ptMaterial.materials.updateFrom( materials, textures );
94
-
95
- // set the environment map
96
- const texture = await new RGBELoader().loadAsync( envMapUrl );
97
- ptRenderer.material.envMapInfo.updateFrom( texture );
98
-
99
- animate();
100
-
101
- // ...
102
-
103
- function animate() {
104
-
105
- // if the camera position changes call "ptRenderer.reset()"
106
-
107
- // update the camera and render one sample
108
- camera.updateMatrixWorld();
109
- ptRenderer.update();
110
-
111
- // copy the current state of the path tracer to canvas to display
112
- renderer.autoClear = false;
113
- fsQuad.material.map = ptRenderer.target.texture;
114
- fsQuad.render( renderer );
115
- renderer.autoClear = true;
116
-
117
- }
118
- ```
119
-
120
- **Blurred Environment Map**
121
-
122
- Using a pre blurred envioronment map can help improve frame convergence time at the cost of sharp environment reflections. If performance is concern then multiple importance sampling can be disabled and blurred environment map used.
123
-
124
- ```js
125
- import { BlurredEnvMapGenerator } from 'three-gpu-pathtracer';
126
-
127
- // ...
128
-
129
- const envMap = await new RGBELoader().loadAsync( envMapUrl );
130
- const generator = new BlurredEnvMapGenerator( renderer );
131
- const blurredEnvMap = generator.generate( envMap, 0.35 );
132
-
133
- // render!
134
-
135
- ```
136
-
137
- ## Dynamic Scenes
138
-
139
- Using the dynamic scene generator the same, frequently updated scene can be converted into a single reusable geometry multiple times and BVH refit which greatly improves subsequent scene updates. See `DynamicPathTracingSceneGenerator` docs for more info.
140
-
141
- ```js
142
- import { DynamicPathTracingSceneGenerator } from 'three-gpu-pathtracer';
143
-
144
- // ... initialize scene etc
145
-
146
- const generator = new DynamicPathTracingSceneGenerator( scene );
147
- const { bvh, textures, materials } = generator.generate( scene );
148
-
149
- // ... update path tracer and render
150
- ```
151
-
152
- ## Asynchronous Scene Generation
153
-
154
- _NOTE WebWorker syntax is inconsistently supported across bundlers and sometimes not supported at all so the PathTracingSceneWorker class is not exported from the package root. If needed the code from src/worker can be copied and modified to accomodate a particular build process._
155
-
156
- ```js
157
- import { PathTracingSceneWorker } from 'three-gpu-pathtracer/src/workers/PathTracingSceneWorker.js';
158
-
159
- // ...
160
-
161
- // initialize the scene and update the material properties with the bvh, materials, etc
162
- const generator = new PathTracingSceneWorker();
163
- const { bvh, textures, materials } = await generator.generate( scene );
164
-
165
- // ...
166
- ```
167
-
168
- # Exports
169
-
170
- ## PathTracingRenderer
171
-
172
- Utility class for tracking and rendering a path traced scene to a render target.
173
-
174
- ### .samples
175
-
176
- ```js
177
- readonly samples : Number
178
- ```
179
-
180
- Number of samples per pixel that have been rendered to the target.
181
-
182
- ### .target
183
-
184
- ```js
185
- readonly target : WebGLRenderTarget
186
- ```
187
-
188
- The target being rendered to. The size of the target is updated with `setSize` and is initialized to a FloatType texture.
189
-
190
- ### .camera
191
-
192
- ```js
193
- camera = null : Camera
194
- ```
195
-
196
- The camera to render with. The view offset of the camera will be updated every sample to enable anti aliasing.
197
-
198
- ### .material
199
-
200
- ```js
201
- material = null : ShaderMaterial
202
- ```
203
-
204
- The Path Tracing material to render. This is expected to be a full screen quad material that respects the "opacity" field for every pixel so samples can be accumulated over time. The material is also expected to have `cameraWorldMatrix` and `invProjectionMatrix` fields of type `Matrix4`.
205
-
206
- ### .tiles
207
-
208
- ```js
209
- tiles = ( 1, 1 ) : Vector2
210
- ```
211
-
212
- Number of tiles on x and y to render to. Can be used to improve the responsiveness of a page while still rendering a high resolution target.
213
-
214
- ### .stableNoise
215
-
216
- ```js
217
- stableNoise = false : Boolean
218
- ```
219
-
220
- Whether to reset the random seed to `0` when restarting the render. If true then a consistent random sample pattern will appear when moving the camera, for example.
221
-
222
- ### .alpha
223
-
224
- ```js
225
- alpha = false : Boolean
226
- ```
227
-
228
- Whether to support rendering scenes with transparent backgrounds. When transparent backgrounds are used two extra render targets are used, custom blending is performed, and PathTracingRenderer.target will change on every completed sample.
229
-
230
- ### constructor
231
-
232
- ```js
233
- constructor( renderer : WebGLRenderer )
234
- ```
235
-
236
- ### .setSize
237
-
238
- ```js
239
- setSize( size : Vector2 ) : void
240
- ```
241
-
242
- Sets the size of the target to render to.
243
-
244
- ### .update
245
-
246
- ```js
247
- update()
248
- ```
249
-
250
- Renders a single sample to the target.
251
-
252
- ### .reset
253
-
254
- ```js
255
- reset() : void
256
- ```
257
-
258
- Resets and restarts the render from scratch.
259
-
260
- ## PathTracingSceneGenerator
261
-
262
- Utility class for generating the set of data required for initializing the path tracing material with a bvh, geometry, materials, and textures.
263
-
264
- ### .generate
265
-
266
- ```js
267
- generate( scene : Object3D, options = {} : Object ) : {
268
- bvh : MeshBVH,
269
- materials : Array<Material>,
270
- textures : Array<Texture>
271
- }
272
- ```
273
-
274
- Merges the geometry in the given scene with an additional "materialIndex" attribute that references the associated material array. Also produces a set of textures referenced by the scene materials.
275
-
276
- ## PathTracingSceneWorker
277
-
278
- _extends PathTracingSceneGenerator_
279
-
280
- See note in [Asyncronous Generation](#asynchronous-generation) use snippet.
281
-
282
- ### .generate
283
-
284
- ```js
285
- async generate( scene : Object3D, options = {} : Object ) : {
286
- bvh : MeshBVH,
287
- materials : Array<Material>,
288
- textures : Array<Texture>
289
- }
290
- ```
291
-
292
- ### .dispose
293
-
294
- ```js
295
- dispose() : void
296
- ```
297
-
298
- ## PhysicalCamera
299
-
300
- _extends THREE.PerspectiveCamera_
301
-
302
- An extension of the three.js PerspectiveCamera with some other parameters associated with depth of field. These parameters otherwise do not affect the camera behavior are are for convenience of use with the PhysicalCameraUniform and pathtracer.
303
-
304
- ### .focusDistance
305
-
306
- ```js
307
- focusDistance = 25 : Number
308
- ```
309
-
310
- The distance from the camera in meters that everything is is perfect focus.
311
-
312
- ### .fStop
313
-
314
- ```js
315
- fStop = 1.4 : Number
316
- ```
317
-
318
- The fstop value of the camera. If this is changed then the `bokehSize` field is implicitly updated.
319
-
320
- ### .bokehSize
321
-
322
- ```js
323
- bokehSize : Number
324
- ```
325
-
326
- The bokeh size as derived from the fStop and focal length in millimeters. If this is set then the fStop is implicitly updated.
327
-
328
- ### .apertureBlades
329
-
330
- ```js
331
- apertureBlades = 0 : Number
332
- ```
333
-
334
- The number of sides / blades on the aperture.
335
-
336
- ### .apertureRotation
337
-
338
- ```js
339
- apertureRotation = 0 : Number
340
- ```
341
-
342
- The rotation of the aperture shape in radians.
343
-
344
- ### .anamorphicRatio
345
-
346
- ```js
347
- anamorphicRatio = 1 : Number
348
- ```
349
-
350
- The anamorphic ratio of the lens. A higher value will stretch the bokeh effect horizontally.
351
-
352
- ## DynamicPathTracingSceneGenerator
353
-
354
- A variation of the path tracing scene generator intended for quickly regenerating a scene BVH representation that updates frequently. Ie those with animated objects or animated skinned geometry.
355
-
356
- In order to quickly update a dynamic scene the same BVH is reused across updates by refitting rather than regenerating. This is significantly faster but also results in a less optimal BVH after significant changes.
357
-
358
- If geometry or materials are added or removed from the scene then `reset` must be called.
359
-
360
- ### constructor
361
-
362
- ```js
363
- constructor( scene : Object3D )
364
- ```
365
-
366
- Takes the scene to convert.
367
-
368
- ### .generate
369
-
370
- ```js
371
- generate() : {
372
- bvh : MeshBVH,
373
- materials : Array<Material>,
374
- textures : Array<Texture>
375
- }
376
- ```
377
-
378
- Generates and refits the bvh to the current scene state. The same bvh, materials, and textures objects are returns after the initial call until `reset` is called.
379
-
380
- ### .reset
381
-
382
- ```js
383
- reset() : void
384
- ```
385
-
386
- Resets the generator so a new BVH is generated. This must be called when geometry, objects, or materials are added or removed from the scene.
387
-
388
- ## BlurredEnvMapGenerator
389
-
390
- Utility for generating a PMREM blurred environment map that can be used with the path tracer.
391
-
392
- ### constructor
393
-
394
- ```js
395
- constructor( renderer : WebGLRenderer )
396
- ```
397
-
398
- ### .generate
399
-
400
- ```js
401
- generate( texture : Texture, blur : Number ) : DataTexture
402
- ```
403
-
404
- Takes a texture to blur and the amount to blur it. Returns a new `DataTexture` that has been PMREM blurred environment map that can have distribution data generated for importance sampling.
405
-
406
- ### .dispose
407
-
408
- ```js
409
- dispose() : void
410
- ```
411
-
412
- Disposes of the temporary files and textures for generation.
413
-
414
- ## MaterialBase
415
-
416
- _extends THREE.ShaderMaterial_
417
-
418
- Convenience base class that adds additional functions and implicitly adds object definitions for all uniforms of the shader to the object.
419
-
420
- ### .setDefine
421
-
422
- ```js
423
- setDefine( name : string, value = undefined : any ) : void
424
- ```
425
-
426
- Sets the define of the given name to the provided value. If the value is set to null or undefined then it is deleted from the defines of the material. If the define changed from the previous value then `Material.needsUpdate` is set to `true`.
427
-
428
- ## PhysicalPathTracingMaterial
429
-
430
- _extends MaterialBase_
431
-
432
- **Uniforms**
433
-
434
- ```js
435
- {
436
- // The number of ray bounces to test. Higher is better quality but slower performance.
437
- bounces = 3 : Number,
438
-
439
- // The physical camera parameters to use
440
- physicalCamera : PhysicalCameraUniform,
441
-
442
- // Geometry and BVH information
443
- bvh: MeshBVHUniformStruct,
444
- normalAttribute: FloatVertexAttributeTexture,
445
- tangentAttribute: FloatVertexAttributeTexture,
446
- uvAttribute: FloatVertexAttributeTexture,
447
- materialIndexAttribute: UIntVertexAttributeTexture,
448
- materials: MaterialsTexture,
449
- textures: RenderTarget2DArray,
450
-
451
- // Environment Map information
452
- envMapInfo: EquirectHdrInfoUniform,
453
- environmentRotation: Matrix3,
454
- environmentIntensity = 1: Number,
455
-
456
- // background blur
457
- backgroundBlur = 0: Number,
458
-
459
- // Factor for alleviating bright pixels from rays that hit diffuse surfaces then
460
- // specular surfaces. Setting this higher alleviates fireflies but will remove some
461
- // specular caustics.
462
- filterGlossyFactor = 0: Number,
463
-
464
- // The colors to use for the gradient background when enabled.
465
- bgGradientTop: Color,
466
- bgGradientBottom: Color,
467
-
468
- // The transparency to render the background with. Note that the "alpha" option
469
- // must be set to true on PathTracingRenderer for this field to work properly.
470
- backgroundAlpha: 1.0,
471
- }
472
- ```
473
-
474
- **Defines**
475
-
476
- ```js
477
- {
478
-
479
- // Whether to use multiple importance sampling to help the image converge more quickly
480
- FEATURE_MIS = 1 : Number,
481
-
482
- // Whether to use the "bg" gradient fields to sample for the background
483
- FEATURE_GRADIENT_BG = 0 : Number
484
-
485
- // The number of transparent pixels to allow on top of existing bounces for object transparency.
486
- TRANSPARENT_TRAVERSALS = 5 : Number,
487
-
488
-
489
- }
490
- ```
491
-
492
- ## RenderTarget2DArray
493
-
494
- _extends WebGLArrayRenderTarget_
495
-
496
- A convenience extension from `WebGLArrayRenderTarget` that affords easily creating a uniform texture array from an array of textures.
497
-
498
- ### .setTextures
499
-
500
- ```js
501
- setTextures(
502
- renderer : WebGLRenderer,
503
- width : Number,
504
- height : Number,
505
- textures : Array<Texture>
506
- ) : void
507
- ```
508
-
509
- Takes the rendering context to updateh the target for, the target dimensions of the texture array, and the array of textures to render into the 2D texture array. Every texture is stretched to the dimensions of the texture array at the same index they are provided in.
510
-
511
- ## PhysicalCameraUniform
512
-
513
- Uniform for storing the camera parameters for use with the shader.
514
-
515
- ### .updateFrom
516
-
517
- ```js
518
- updateFrom( camera : PerspectiveCamera | PhysicalCamera ) : void
519
- ```
520
-
521
- Copies all fields from the passed PhysicalCamera if available otherwise the defaults are used.
522
-
523
- ## MaterialsTexture
524
-
525
- _extends DataTexture_
526
-
527
- Helper texture uniform for encoding materials as texture data.
528
-
529
- ### .setSide
530
-
531
- ```js
532
- setSide( index : Number, side : FrontSide | BackSide | DoubleSide ) : void
533
- ```
534
-
535
- Sets the side to render for the given material.
536
-
537
- ### .setMatte
538
-
539
- ```js
540
- setMatte( index : Number, matte : Boolean ) : void
541
- ```
542
-
543
- Sets whether or not the material of the given index is matte or not. When "true" the background is rendered in place of the material.
544
-
545
- ### .updateFrom
546
-
547
- ```js
548
- updateFrom( materials : Array<Material>, textures : Array<Texture> ) : void
549
- ```
550
-
551
- Updates the size and values of the texture to align with the provided set of materials and textures.
552
-
553
- The "matte" and "side" values must be updated explicitly.
554
-
555
- ## EquirectHdrInfoUniform
556
-
557
- Stores the environment map contents along with the intensity distribution information to support multiple importance sampling.
558
-
559
- ### .updateFrom
560
-
561
- ```js
562
- updateFrom( environmentMap : Texture ) : void
563
- ```
564
-
565
- Takes an environment map to process into something usable by the path tracer. Is expected to be a DataTexture so the data can be read.
566
-
567
- ## Functions
568
-
569
- ### mergeMeshes
570
-
571
- ```js
572
- mergeMeshes( meshes : Array<Mesh> ) : {
573
- materials : Array<Material>,
574
- textures : Array<Textures>,
575
- geometry : BufferGeometry
576
- }
577
- ```
578
-
579
- Merges the set of meshes into a single geometry with a `materialIndex` vertex attribute included on the geometry identifying the associated material in the returned `materials` array.
580
-
581
- ## Shader Chunks
582
-
583
- **shaderMaterialSampling**
584
-
585
- Set of functions for performing material scatter and PDF sampling. See the [implementation](https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/src/shader/shaderMaterialSampling.js) for full list of functions.
586
-
587
- **shaderStructs**
588
-
589
- Material struct definition for use with uniforms. See the [implementation](https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/src/shader/shaderStructs.js) for full list of functions.
590
-
591
- **shaderUtils**
592
-
593
- Set of randomness and other light transmport utilities for use in a shader. See the [implementation](https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/src/shader/shaderUtils.js) for full list of functions.
594
-
595
- # Gotchas
596
-
597
- - The project requires use of WebGL2.
598
- - All textures must use the same wrap and interpolation flags.
599
- - Texture repeat, rotation, and center properties are not supported.
600
-
601
- # Screenshots
602
-
603
- ![](https://user-images.githubusercontent.com/734200/162584469-68e6df38-92da-4a13-b352-ca0bdea14548.png)
604
-
605
- <p align="center">
606
- <i>Sample materials</i>
607
- </p>
608
-
609
- ![](https://user-images.githubusercontent.com/734200/163835927-be75d2c0-f27b-4e4b-a3eb-2371043fa5e1.png)
610
-
611
- ![](https://user-images.githubusercontent.com/734200/163839431-ed75e64d-9ae4-4423-afca-55162a44873e.png)
612
-
613
- <p align="center">
614
- <i>"SD Macross City Standoff Diorama" scene by <a href="https://sketchfab.com/3d-models/sd-macross-city-standoff-diorama-b154220f7e7441799d6be2f7ff9658c7">tipatat</a></i>
615
- </p>
616
-
617
- ![](./docs/interior-scene-cropped.png)
618
-
619
- <p align="center">
620
- <i>"Interior Scene" model by <a href="https://sketchfab.com/3d-models/interior-scene-45ddbbc4c2dc4f8ca9ed99da9a78326a">Allay Design</a></i>
621
- </p>
622
-
623
- ![](https://user-images.githubusercontent.com/734200/161820794-df0da371-ee5c-4368-9e7b-5e7daf6cf3c7.png)
624
-
625
- ![](https://user-images.githubusercontent.com/734200/162550315-3cdabf40-3dea-4d7d-bcfc-eb543eea2d93.png)
626
-
627
- <p align="center">
628
- <i>Perseverance Rover, Ingenuity Helicopter models by <a href="https://mars.nasa.gov/resources/25042/mars-perseverance-rover-3d-model/">NASA / JPL-Caltech</a></i>
629
- </p>
630
-
631
- ![](https://user-images.githubusercontent.com/734200/161877900-566652e4-c799-4940-bccb-0c8f4cea5387.png)
632
-
633
- <p align="center">
634
- <i>Gelatinous Cube model by <a href="https://sketchfab.com/3d-models/gelatinous-cube-e08385238f4d4b59b012233a9fbdca21">glenatron</a></i>
635
- </p>
636
-
637
- ![](https://user-images.githubusercontent.com/734200/161822206-c27bf594-d648-4735-868e-4baf4e414802.png)
638
-
639
- ![](https://user-images.githubusercontent.com/734200/161822214-eace4297-03c4-4adc-b472-efe29a862685.png)
640
-
641
- <p align="center">
642
- <i>Lego models courtesy of the <a href="https://omr.ldraw.org/">LDraw Official Model Repository</a></i>
643
- </p>
644
-
645
- ![](https://user-images.githubusercontent.com/734200/161877196-7ae2769e-7e54-4694-9ca8-e8f5219d1c2d.png)
646
-
647
- <p align="center">
648
- <i>Octopus Tea model by <a href="https://sketchfab.com/3d-models/cartoon-octopus-takes-a-tea-bath-107260cf0fd24202a67eb037a6c760a5
649
- ">AzTiZ</a></i>
650
- </p>
651
-
652
- ### Resources
653
-
654
- [Raytracing in One Weekend Book](https://raytracing.github.io/)
655
-
656
- [PBR Book](https://pbr-book.org/)
657
-
658
- [knightcrawler25/GLSL-PathTracer](https://github.com/knightcrawler25/GLSL-PathTracer/)
659
-
660
-
1
+ # three-gpu-pathtracer
2
+
3
+ [![npm version](https://img.shields.io/npm/v/three-gpu-pathtracer.svg?style=flat-square)](https://www.npmjs.com/package/three-gpu-pathtracer)
4
+ [![lgtm code quality](https://img.shields.io/lgtm/grade/javascript/g/gkjohnson/three-gpu-pathtracer.svg?style=flat-square&label=code-quality)](https://lgtm.com/projects/g/gkjohnson/three-gpu-pathtracer/)
5
+ [![build](https://img.shields.io/github/workflow/status/gkjohnson/three-gpu-pathtracer/Node.js%20CI?style=flat-square&label=build)](https://github.com/gkjohnson/three-gpu-pathtracer/actions)
6
+ [![github](https://flat.badgen.net/badge/icon/github?icon=github&label)](https://github.com/gkjohnson/three-gpu-pathtracer/)
7
+ [![twitter](https://flat.badgen.net/twitter/follow/garrettkjohnson)](https://twitter.com/garrettkjohnson)
8
+ [![sponsors](https://img.shields.io/github/sponsors/gkjohnson?style=flat-square&color=1da1f2)](https://github.com/sponsors/gkjohnson/)
9
+
10
+ ![](https://user-images.githubusercontent.com/734200/162287477-96696b18-890b-4c1b-8a73-d662e577cc48.png)
11
+
12
+ Path tracing project using [three-mesh-bvh](https://github.com/gkjohnson/three-mesh-bvh) and WebGL 2 to accelerate high quality, physically based rendering on the GPU. Features include support for GGX surface model, material information, textures, normal maps, emission, environment maps, tiled rendering, and more!
13
+
14
+ _More features and capabilities in progress!_
15
+
16
+ # Examples
17
+
18
+ **Beauty Demos**
19
+
20
+ [Physically Based Materials](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/index.html)
21
+
22
+ [Lego Models](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/lego.html)
23
+
24
+ [Interior Scene](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/interior.html)
25
+
26
+ [Depth of Field](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/depthOfField.html)
27
+
28
+ **Features**
29
+
30
+ [Skinned Geometry Support](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/skinnedMesh.html)
31
+
32
+ [Morph Target Support](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/skinnedMesh.html#morphtarget)
33
+
34
+ **Test Scenes**
35
+
36
+ [Material Test Orb](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/materialBall.html)
37
+
38
+ [Transmission Preset Orb](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/materialBall.html#transmission)
39
+
40
+ **Light Baking**
41
+
42
+ [Ambient Occlusion Material](https://gkjohnson.github.io/three-gpu-pathtracer/example/bundle/aoRender.html)
43
+
44
+ # Use
45
+
46
+ **Basic Renderer**
47
+
48
+ ```js
49
+ import * as THREE from 'three';
50
+ import { FullScreenQuad } from 'three/examples/jsm/postprocessing/Pass.js';
51
+ import {
52
+ PathTracingSceneGenerator,
53
+ PathTracingRenderer,
54
+ PhysicalPathTracingMaterial,
55
+ } from 'three-gpu-pathtracer';
56
+
57
+ // init scene, renderer, camera, controls, etc
58
+
59
+ // initialize the path tracing material and renderer
60
+ const ptMaterial = new PhysicalPathTracingMaterial();
61
+ const ptRenderer = new PathTracingRenderer( renderer );
62
+ ptRenderer.setSize( window.innerWidth, window.innerHeight );
63
+ ptRenderer.camera = camera;
64
+ ptRenderer.material = ptMaterial;
65
+
66
+ // if rendering transparent background
67
+ ptRenderer.alpha = true;
68
+
69
+ // init quad for rendering to the canvas
70
+ const fsQuad = new FullScreenQuad( new THREE.MeshBasicMaterial( {
71
+ map: ptRenderer.target.texture,
72
+
73
+ // if rendering transparent background
74
+ blending: THREE.CustomBlending,
75
+ } ) );
76
+
77
+ // ensure scene matrices are up to date
78
+ scene.updateMatrixWorld();
79
+
80
+ // initialize the scene and update the material properties with the bvh, materials, etc
81
+ const generator = new PathTracingSceneGenerator();
82
+ const { bvh, textures, materials } = generator.generate( scene );
83
+
84
+ // update bvh and geometry attribute textures
85
+ ptMaterial.bvh.updateFrom( bvh );
86
+ ptMaterial.normalAttribute.updateFrom( geometry.attributes.normal );
87
+ ptMaterial.tangentAttribute.updateFrom( geometry.attributes.tangent );
88
+ ptMaterial.uvAttribute.updateFrom( geometry.attributes.uv );
89
+
90
+ // update materials and texture arrays
91
+ ptMaterial.materialIndexAttribute.updateFrom( geometry.attributes.materialIndex );
92
+ ptMaterial.textures.setTextures( renderer, 2048, 2048, textures );
93
+ ptMaterial.materials.updateFrom( materials, textures );
94
+
95
+ // set the environment map
96
+ const texture = await new RGBELoader().loadAsync( envMapUrl );
97
+ ptRenderer.material.envMapInfo.updateFrom( texture );
98
+
99
+ animate();
100
+
101
+ // ...
102
+
103
+ function animate() {
104
+
105
+ // if the camera position changes call "ptRenderer.reset()"
106
+
107
+ // update the camera and render one sample
108
+ camera.updateMatrixWorld();
109
+ ptRenderer.update();
110
+
111
+ // if using alpha = true then the target texture will change every frame
112
+ // so we must retrieve it before render.
113
+ fsQuad.material.map = ptRenderer.target.texture;
114
+
115
+ // copy the current state of the path tracer to canvas to display
116
+ fsQuad.render( renderer );
117
+
118
+ }
119
+ ```
120
+
121
+ **Blurred Environment Map**
122
+
123
+ Using a pre blurred envioronment map can help improve frame convergence time at the cost of sharp environment reflections. If performance is concern then multiple importance sampling can be disabled and blurred environment map used.
124
+
125
+ ```js
126
+ import { BlurredEnvMapGenerator } from 'three-gpu-pathtracer';
127
+
128
+ // ...
129
+
130
+ const envMap = await new RGBELoader().loadAsync( envMapUrl );
131
+ const generator = new BlurredEnvMapGenerator( renderer );
132
+ const blurredEnvMap = generator.generate( envMap, 0.35 );
133
+
134
+ // render!
135
+
136
+ ```
137
+
138
+ ## Dynamic Scenes
139
+
140
+ Using the dynamic scene generator the same, frequently updated scene can be converted into a single reusable geometry multiple times and BVH refit which greatly improves subsequent scene updates. See `DynamicPathTracingSceneGenerator` docs for more info.
141
+
142
+ ```js
143
+ import { DynamicPathTracingSceneGenerator } from 'three-gpu-pathtracer';
144
+
145
+ // ... initialize scene etc
146
+
147
+ const generator = new DynamicPathTracingSceneGenerator( scene );
148
+ const { bvh, textures, materials } = generator.generate( scene );
149
+
150
+ // ... update path tracer and render
151
+ ```
152
+
153
+ ## Asynchronous Scene Generation
154
+
155
+ _NOTE WebWorker syntax is inconsistently supported across bundlers and sometimes not supported at all so the PathTracingSceneWorker class is not exported from the package root. If needed the code from src/worker can be copied and modified to accomodate a particular build process._
156
+
157
+ ```js
158
+ import { PathTracingSceneWorker } from 'three-gpu-pathtracer/src/workers/PathTracingSceneWorker.js';
159
+
160
+ // ...
161
+
162
+ // initialize the scene and update the material properties with the bvh, materials, etc
163
+ const generator = new PathTracingSceneWorker();
164
+ const { bvh, textures, materials } = await generator.generate( scene );
165
+
166
+ // ...
167
+ ```
168
+
169
+ # Exports
170
+
171
+ ## PathTracingRenderer
172
+
173
+ Utility class for tracking and rendering a path traced scene to a render target.
174
+
175
+ ### .samples
176
+
177
+ ```js
178
+ readonly samples : Number
179
+ ```
180
+
181
+ Number of samples per pixel that have been rendered to the target.
182
+
183
+ ### .target
184
+
185
+ ```js
186
+ readonly target : WebGLRenderTarget
187
+ ```
188
+
189
+ The target being rendered to. The size of the target is updated with `setSize` and is initialized to a FloatType texture.
190
+
191
+ ### .camera
192
+
193
+ ```js
194
+ camera = null : Camera
195
+ ```
196
+
197
+ The camera to render with. The view offset of the camera will be updated every sample to enable anti aliasing.
198
+
199
+ ### .material
200
+
201
+ ```js
202
+ material = null : ShaderMaterial
203
+ ```
204
+
205
+ The Path Tracing material to render. This is expected to be a full screen quad material that respects the "opacity" field for every pixel so samples can be accumulated over time. The material is also expected to have `cameraWorldMatrix` and `invProjectionMatrix` fields of type `Matrix4`.
206
+
207
+ ### .tiles
208
+
209
+ ```js
210
+ tiles = ( 1, 1 ) : Vector2
211
+ ```
212
+
213
+ Number of tiles on x and y to render to. Can be used to improve the responsiveness of a page while still rendering a high resolution target.
214
+
215
+ ### .stableNoise
216
+
217
+ ```js
218
+ stableNoise = false : Boolean
219
+ ```
220
+
221
+ Whether to reset the random seed to `0` when restarting the render. If true then a consistent random sample pattern will appear when moving the camera, for example.
222
+
223
+ ### .alpha
224
+
225
+ ```js
226
+ alpha = false : Boolean
227
+ ```
228
+
229
+ Whether to support rendering scenes with transparent backgrounds. When transparent backgrounds are used two extra render targets are used, custom blending is performed, and PathTracingRenderer.target will change on every completed sample.
230
+
231
+ ### constructor
232
+
233
+ ```js
234
+ constructor( renderer : WebGLRenderer )
235
+ ```
236
+
237
+ ### .setSize
238
+
239
+ ```js
240
+ setSize( size : Vector2 ) : void
241
+ ```
242
+
243
+ Sets the size of the target to render to.
244
+
245
+ ### .update
246
+
247
+ ```js
248
+ update()
249
+ ```
250
+
251
+ Renders a single sample to the target.
252
+
253
+ ### .reset
254
+
255
+ ```js
256
+ reset() : void
257
+ ```
258
+
259
+ Resets and restarts the render from scratch.
260
+
261
+ ## PathTracingSceneGenerator
262
+
263
+ Utility class for generating the set of data required for initializing the path tracing material with a bvh, geometry, materials, and textures.
264
+
265
+ ### .generate
266
+
267
+ ```js
268
+ generate( scene : Object3D, options = {} : Object ) : {
269
+ bvh : MeshBVH,
270
+ materials : Array<Material>,
271
+ textures : Array<Texture>
272
+ }
273
+ ```
274
+
275
+ Merges the geometry in the given scene with an additional "materialIndex" attribute that references the associated material array. Also produces a set of textures referenced by the scene materials.
276
+
277
+ ## PathTracingSceneWorker
278
+
279
+ _extends PathTracingSceneGenerator_
280
+
281
+ See note in [Asyncronous Generation](#asynchronous-generation) use snippet.
282
+
283
+ ### .generate
284
+
285
+ ```js
286
+ async generate( scene : Object3D, options = {} : Object ) : {
287
+ bvh : MeshBVH,
288
+ materials : Array<Material>,
289
+ textures : Array<Texture>
290
+ }
291
+ ```
292
+
293
+ ### .dispose
294
+
295
+ ```js
296
+ dispose() : void
297
+ ```
298
+
299
+ ## PhysicalCamera
300
+
301
+ _extends THREE.PerspectiveCamera_
302
+
303
+ An extension of the three.js PerspectiveCamera with some other parameters associated with depth of field. These parameters otherwise do not affect the camera behavior are are for convenience of use with the PhysicalCameraUniform and pathtracer.
304
+
305
+ ### .focusDistance
306
+
307
+ ```js
308
+ focusDistance = 25 : Number
309
+ ```
310
+
311
+ The distance from the camera in meters that everything is is perfect focus.
312
+
313
+ ### .fStop
314
+
315
+ ```js
316
+ fStop = 1.4 : Number
317
+ ```
318
+
319
+ The fstop value of the camera. If this is changed then the `bokehSize` field is implicitly updated.
320
+
321
+ ### .bokehSize
322
+
323
+ ```js
324
+ bokehSize : Number
325
+ ```
326
+
327
+ The bokeh size as derived from the fStop and focal length in millimeters. If this is set then the fStop is implicitly updated.
328
+
329
+ ### .apertureBlades
330
+
331
+ ```js
332
+ apertureBlades = 0 : Number
333
+ ```
334
+
335
+ The number of sides / blades on the aperture.
336
+
337
+ ### .apertureRotation
338
+
339
+ ```js
340
+ apertureRotation = 0 : Number
341
+ ```
342
+
343
+ The rotation of the aperture shape in radians.
344
+
345
+ ### .anamorphicRatio
346
+
347
+ ```js
348
+ anamorphicRatio = 1 : Number
349
+ ```
350
+
351
+ The anamorphic ratio of the lens. A higher value will stretch the bokeh effect horizontally.
352
+
353
+ ## DynamicPathTracingSceneGenerator
354
+
355
+ A variation of the path tracing scene generator intended for quickly regenerating a scene BVH representation that updates frequently. Ie those with animated objects or animated skinned geometry.
356
+
357
+ In order to quickly update a dynamic scene the same BVH is reused across updates by refitting rather than regenerating. This is significantly faster but also results in a less optimal BVH after significant changes.
358
+
359
+ If geometry or materials are added or removed from the scene then `reset` must be called.
360
+
361
+ ### constructor
362
+
363
+ ```js
364
+ constructor( scene : Object3D )
365
+ ```
366
+
367
+ Takes the scene to convert.
368
+
369
+ ### .generate
370
+
371
+ ```js
372
+ generate() : {
373
+ bvh : MeshBVH,
374
+ materials : Array<Material>,
375
+ textures : Array<Texture>
376
+ }
377
+ ```
378
+
379
+ Generates and refits the bvh to the current scene state. The same bvh, materials, and textures objects are returns after the initial call until `reset` is called.
380
+
381
+ ### .reset
382
+
383
+ ```js
384
+ reset() : void
385
+ ```
386
+
387
+ Resets the generator so a new BVH is generated. This must be called when geometry, objects, or materials are added or removed from the scene.
388
+
389
+ ## BlurredEnvMapGenerator
390
+
391
+ Utility for generating a PMREM blurred environment map that can be used with the path tracer.
392
+
393
+ ### constructor
394
+
395
+ ```js
396
+ constructor( renderer : WebGLRenderer )
397
+ ```
398
+
399
+ ### .generate
400
+
401
+ ```js
402
+ generate( texture : Texture, blur : Number ) : DataTexture
403
+ ```
404
+
405
+ Takes a texture to blur and the amount to blur it. Returns a new `DataTexture` that has been PMREM blurred environment map that can have distribution data generated for importance sampling.
406
+
407
+ ### .dispose
408
+
409
+ ```js
410
+ dispose() : void
411
+ ```
412
+
413
+ Disposes of the temporary files and textures for generation.
414
+
415
+ ## MaterialBase
416
+
417
+ _extends THREE.ShaderMaterial_
418
+
419
+ Convenience base class that adds additional functions and implicitly adds object definitions for all uniforms of the shader to the object.
420
+
421
+ ### .setDefine
422
+
423
+ ```js
424
+ setDefine( name : string, value = undefined : any ) : void
425
+ ```
426
+
427
+ Sets the define of the given name to the provided value. If the value is set to null or undefined then it is deleted from the defines of the material. If the define changed from the previous value then `Material.needsUpdate` is set to `true`.
428
+
429
+ ## PhysicalPathTracingMaterial
430
+
431
+ _extends MaterialBase_
432
+
433
+ **Uniforms**
434
+
435
+ ```js
436
+ {
437
+ // The number of ray bounces to test. Higher is better quality but slower performance.
438
+ bounces = 3 : Number,
439
+
440
+ // The physical camera parameters to use
441
+ physicalCamera : PhysicalCameraUniform,
442
+
443
+ // Geometry and BVH information
444
+ bvh: MeshBVHUniformStruct,
445
+ normalAttribute: FloatVertexAttributeTexture,
446
+ tangentAttribute: FloatVertexAttributeTexture,
447
+ uvAttribute: FloatVertexAttributeTexture,
448
+ materialIndexAttribute: UIntVertexAttributeTexture,
449
+ materials: MaterialsTexture,
450
+ textures: RenderTarget2DArray,
451
+
452
+ // Environment Map information
453
+ envMapInfo: EquirectHdrInfoUniform,
454
+ environmentRotation: Matrix3,
455
+ environmentIntensity = 1: Number,
456
+
457
+ // background blur
458
+ backgroundBlur = 0: Number,
459
+
460
+ // Factor for alleviating bright pixels from rays that hit diffuse surfaces then
461
+ // specular surfaces. Setting this higher alleviates fireflies but will remove some
462
+ // specular caustics.
463
+ filterGlossyFactor = 0: Number,
464
+
465
+ // The colors to use for the gradient background when enabled.
466
+ bgGradientTop: Color,
467
+ bgGradientBottom: Color,
468
+
469
+ // The transparency to render the background with. Note that the "alpha" option
470
+ // must be set to true on PathTracingRenderer for this field to work properly.
471
+ backgroundAlpha: 1.0,
472
+ }
473
+ ```
474
+
475
+ **Defines**
476
+
477
+ ```js
478
+ {
479
+
480
+ // Whether to use multiple importance sampling to help the image converge more quickly
481
+ FEATURE_MIS = 1 : Number,
482
+
483
+ // Whether to use the "bg" gradient fields to sample for the background
484
+ FEATURE_GRADIENT_BG = 0 : Number
485
+
486
+ // The number of transparent pixels to allow on top of existing bounces for object transparency.
487
+ TRANSPARENT_TRAVERSALS = 5 : Number,
488
+
489
+
490
+ }
491
+ ```
492
+
493
+ ## RenderTarget2DArray
494
+
495
+ _extends WebGLArrayRenderTarget_
496
+
497
+ A convenience extension from `WebGLArrayRenderTarget` that affords easily creating a uniform texture array from an array of textures.
498
+
499
+ ### .setTextures
500
+
501
+ ```js
502
+ setTextures(
503
+ renderer : WebGLRenderer,
504
+ width : Number,
505
+ height : Number,
506
+ textures : Array<Texture>
507
+ ) : void
508
+ ```
509
+
510
+ Takes the rendering context to updateh the target for, the target dimensions of the texture array, and the array of textures to render into the 2D texture array. Every texture is stretched to the dimensions of the texture array at the same index they are provided in.
511
+
512
+ ## PhysicalCameraUniform
513
+
514
+ Uniform for storing the camera parameters for use with the shader.
515
+
516
+ ### .updateFrom
517
+
518
+ ```js
519
+ updateFrom( camera : PerspectiveCamera | PhysicalCamera ) : void
520
+ ```
521
+
522
+ Copies all fields from the passed PhysicalCamera if available otherwise the defaults are used.
523
+
524
+ ## MaterialsTexture
525
+
526
+ _extends DataTexture_
527
+
528
+ Helper texture uniform for encoding materials as texture data.
529
+
530
+ ### .setSide
531
+
532
+ ```js
533
+ setSide( index : Number, side : FrontSide | BackSide | DoubleSide ) : void
534
+ ```
535
+
536
+ Sets the side to render for the given material.
537
+
538
+ ### .setMatte
539
+
540
+ ```js
541
+ setMatte( index : Number, matte : Boolean ) : void
542
+ ```
543
+
544
+ Sets whether or not the material of the given index is matte or not. When "true" the background is rendered in place of the material.
545
+
546
+ ### .setCastShadow
547
+
548
+ ```js
549
+ setCastShadow( index : Number, enabled : Boolean ) : void
550
+ ```
551
+
552
+ Sets whether or not the material of the given index will cast shadows. When "false" materials will not cast shadows on diffuse surfaces but will still be reflected. This is a good setting for lighting enclosed interiors with environment lighting.
553
+
554
+ ### .updateFrom
555
+
556
+ ```js
557
+ updateFrom( materials : Array<Material>, textures : Array<Texture> ) : void
558
+ ```
559
+
560
+ Updates the size and values of the texture to align with the provided set of materials and textures.
561
+
562
+ The "matte" and "side" values must be updated explicitly.
563
+
564
+ ## EquirectHdrInfoUniform
565
+
566
+ Stores the environment map contents along with the intensity distribution information to support multiple importance sampling.
567
+
568
+ ### .updateFrom
569
+
570
+ ```js
571
+ updateFrom( environmentMap : Texture ) : void
572
+ ```
573
+
574
+ Takes an environment map to process into something usable by the path tracer. Is expected to be a DataTexture so the data can be read.
575
+
576
+ ## Functions
577
+
578
+ ### mergeMeshes
579
+
580
+ ```js
581
+ mergeMeshes( meshes : Array<Mesh> ) : {
582
+ materials : Array<Material>,
583
+ textures : Array<Textures>,
584
+ geometry : BufferGeometry
585
+ }
586
+ ```
587
+
588
+ Merges the set of meshes into a single geometry with a `materialIndex` vertex attribute included on the geometry identifying the associated material in the returned `materials` array.
589
+
590
+ ## Shader Chunks
591
+
592
+ **shaderMaterialSampling**
593
+
594
+ Set of functions for performing material scatter and PDF sampling. See the [implementation](https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/src/shader/shaderMaterialSampling.js) for full list of functions.
595
+
596
+ **shaderStructs**
597
+
598
+ Material struct definition for use with uniforms. See the [implementation](https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/src/shader/shaderStructs.js) for full list of functions.
599
+
600
+ **shaderUtils**
601
+
602
+ Set of randomness and other light transmport utilities for use in a shader. See the [implementation](https://github.com/gkjohnson/three-gpu-pathtracer/blob/main/src/shader/shaderUtils.js) for full list of functions.
603
+
604
+ # Gotchas
605
+
606
+ - The project requires use of WebGL2.
607
+ - All textures must use the same wrap and interpolation flags.
608
+
609
+ # Screenshots
610
+
611
+ ![](https://user-images.githubusercontent.com/734200/162584469-68e6df38-92da-4a13-b352-ca0bdea14548.png)
612
+
613
+ <p align="center">
614
+ <i>Sample materials</i>
615
+ </p>
616
+
617
+ ![](https://user-images.githubusercontent.com/734200/163835927-be75d2c0-f27b-4e4b-a3eb-2371043fa5e1.png)
618
+
619
+ ![](https://user-images.githubusercontent.com/734200/163839431-ed75e64d-9ae4-4423-afca-55162a44873e.png)
620
+
621
+ <p align="center">
622
+ <i>"SD Macross City Standoff Diorama" scene by <a href="https://sketchfab.com/3d-models/sd-macross-city-standoff-diorama-b154220f7e7441799d6be2f7ff9658c7">tipatat</a></i>
623
+ </p>
624
+
625
+ ![](./docs/interior-scene-cropped.png)
626
+
627
+ <p align="center">
628
+ <i>"Interior Scene" model by <a href="https://sketchfab.com/3d-models/interior-scene-45ddbbc4c2dc4f8ca9ed99da9a78326a">Allay Design</a></i>
629
+ </p>
630
+
631
+ ![](https://user-images.githubusercontent.com/734200/161820794-df0da371-ee5c-4368-9e7b-5e7daf6cf3c7.png)
632
+
633
+ ![](https://user-images.githubusercontent.com/734200/162550315-3cdabf40-3dea-4d7d-bcfc-eb543eea2d93.png)
634
+
635
+ <p align="center">
636
+ <i>Perseverance Rover, Ingenuity Helicopter models by <a href="https://mars.nasa.gov/resources/25042/mars-perseverance-rover-3d-model/">NASA / JPL-Caltech</a></i>
637
+ </p>
638
+
639
+ ![](https://user-images.githubusercontent.com/734200/161877900-566652e4-c799-4940-bccb-0c8f4cea5387.png)
640
+
641
+ <p align="center">
642
+ <i>Gelatinous Cube model by <a href="https://sketchfab.com/3d-models/gelatinous-cube-e08385238f4d4b59b012233a9fbdca21">glenatron</a></i>
643
+ </p>
644
+
645
+ ![](https://user-images.githubusercontent.com/734200/161822206-c27bf594-d648-4735-868e-4baf4e414802.png)
646
+
647
+ ![](https://user-images.githubusercontent.com/734200/161822214-eace4297-03c4-4adc-b472-efe29a862685.png)
648
+
649
+ <p align="center">
650
+ <i>Lego models courtesy of the <a href="https://omr.ldraw.org/">LDraw Official Model Repository</a></i>
651
+ </p>
652
+
653
+ ![](https://user-images.githubusercontent.com/734200/161877196-7ae2769e-7e54-4694-9ca8-e8f5219d1c2d.png)
654
+
655
+ <p align="center">
656
+ <i>Octopus Tea model by <a href="https://sketchfab.com/3d-models/cartoon-octopus-takes-a-tea-bath-107260cf0fd24202a67eb037a6c760a5
657
+ ">AzTiZ</a></i>
658
+ </p>
659
+
660
+ ![](https://user-images.githubusercontent.com/734200/173212652-de6a83e5-dd2c-49b5-8ed7-484ff8969b5b.png)
661
+ <p align="center">
662
+ <i>Botanists Study model by <a href="https://sketchfab.com/3d-models/the-botanists-study-8b7b5743b1c848ed8ea58f5518c44e7e">riikkakilpelainen</a></i>
663
+ </p>
664
+
665
+ ![](https://user-images.githubusercontent.com/734200/173170459-849b9343-efe3-4635-8719-346511472965.png)
666
+ <p align="center">
667
+ <i>Japanese Bridge Garden model by <a href="https://sketchfab.com/3d-models/japanese-bridge-garden-d122e17593eb4012913cde927486d15a">kristenlee</a></i>
668
+ </p>
669
+
670
+ ### Resources
671
+
672
+ [Raytracing in One Weekend Book](https://raytracing.github.io/)
673
+
674
+ [PBR Book](https://pbr-book.org/)
675
+
676
+ [knightcrawler25/GLSL-PathTracer](https://github.com/knightcrawler25/GLSL-PathTracer/)
677
+
678
+