Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
erichlof committed Mar 8, 2024
1 parent 1e355cd commit 8a39a29
Showing 1 changed file with 5 additions and 1 deletion.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ For comparison, here is a real photograph of the original Cornell Box vs. a rend

* [Quadric Shapes Explorer](https://erichlof.github.io/THREE.js-PathTracing-Renderer/Quadric_Shapes_Explorer.html) This demo lets you explore the endless variety of quadric shapes. All quadrics are defined with a set of parameters (usually labeled A through J) that describe the type and look of the shape. I recently came across a little gem of a research paper entitled "Ray Tracing Arbitrary Objects on the GPU" by Wood et al. from back in 2004. In the paper the authors describe an efficient method of storing the quadric shape parameters (A-J) inside a tidy 4x4 matrix, which fits nicely in GPU memory. Any quadric shape imaginable can easily be constructed by adjusting the A-J parameters inside the 4x4 matrix. I implemented their technique for this demo. Taking it a step further, I provided a GUI menu list of standard shape presets (Sphere, Cone, Paraboloid, etc), so you can see how the more well-known shapes' parameters are set. I also turned these A-J quadric shape parameters into handy GUI sliders so you can easily play around with the parameters and watch the path-traced 3D shapes change right before your eyes! <br>

* [Transforming Quadric Geometry Demo](https://erichlof.github.io/THREE.js-PathTracing-Renderer/Transforming_Quadric_Geometry_Showcase.html) Using the game engine version of the three.js path tracer, this demo shows how to create multiple objects (a bunch of 'THREE.Object3d()'s, each with its own transform) on the JavaScript side when initializing three.js, and then send the objects over to the GPU for realtime pathtracing. The nice thing about having my pathtracer sitting on top of three.js is that I can use its built-in transformations such as Translate, Rotate, and Scale. Since these shapes are all quadrics made from different parameters, I also included clipping parameters so you can have partial shapes and can even animate the cutting process! *Note: this demo may take several seconds to compile* <br> <br>
* [Transforming Quadric Geometry Demo](https://erichlof.github.io/THREE.js-PathTracing-Renderer/Transforming_Quadric_Geometry_Showcase.html) Using the game engine version of the three.js path tracer, this demo shows how to create multiple objects (a bunch of 'THREE.Object3d()'s, each with its own transform) on the JavaScript side when initializing three.js, and then send the objects over to the GPU for realtime pathtracing. The nice thing about having my pathtracer sitting on top of three.js is that I can use its built-in transformations such as Translate, Rotate, and Scale. Since these shapes are all quadrics made from different parameters, I also included clipping parameters so you can have partial shapes and can even animate the cutting process! *Note: this demo may take several seconds to compile* <br>

* [Cheap Torus Alternative Demo](https://erichlof.github.io/THREE.js-PathTracing-Renderer/Cheap_Torus.html) Introducing the Cheap Torus, my custom approximation to the beautiful Torus shape. Historically, the Torus has always been difficult and expensive to ray trace, because it is a quartic (degree 4) shape which requires you to solve for the roots of a quartic equation. I've tried many different quartic solvers out there and they are either too finnicky to use and get looking right, or too expensive to efficiently run on normal consumer hardware and mobile. And then after doing all that work, you still get rendering artifacts like gaps and thin cracks at larger scales, due to limited GPU shader float precision. So, determined to efficiently render a Torus that would be air-tight at all scales, I set out on a journey to find a better solution. Along this rabbit hole (ha), I discovered a cool trick of combining 2 simple quadric shapes (only degree 2), namely the Hyperboloid (hourglass) and the truncated Sphere (both top and bottom removed). When these 2 simple shapes are combined in just the right way, we get a very close approximation to the Torus, free of gap artifacts at all scales and very fast to render. Now we can finally have multiple Torii all over our scenes without worrying about precision artifacts or performance costs - enjoy! <br> <br>

<h3>Constructive Solid Geometry(CSG) Demos</h3>

Expand Down Expand Up @@ -334,6 +336,8 @@ A technical note about what you are seeing: The data arrives to the fragment sha

<h2>Updates</h2>

* March 8, 2024: Over the last year on and off, I have been working on an efficient method to ray trace a Torus. At long last, I present the Cheap Torus - my custom approximation to the beautiful Torus shape. Historically, the Torus has always been difficult and expensive to ray trace, because it is a quartic (degree 4) shape which requires you to solve for the roots of a quartic equation. I've tried many different quartic solvers out there (I even tried ray marching a torus signed distance field, or sdf) and they are either too finnicky to use and get looking right, or too expensive to efficiently run on normal hardware and mobile. And then after doing all that work, you still get rendering artifacts like gaps and thin cracks at larger scales, due to limited GPU shader float precision. So, determined to come up with a better solution, I set out on a long journey to efficiently render a Torus that would be air-tight at all scales. Along this rabbit hole (ha), I discovered a cool trick of combining 2 simple quadric shapes (only degree 2), namely the Hyperboloid (hourglass) and the truncated Sphere (both top and bottom removed). When these 2 simple shapes are combined in just the right way, we get a very close approximation to the Torus, free of gap artifacts at all scales and very fast to render. The Hyperboloid (hourglass) is used for the inner part of the Torus, while the top-and-bottom-truncated Sphere is used for the outside of the Torus. Where these 2 shapes meet, there was an annoying seam, so I hid this seam by slightly bending the surface normals reported back from the 2 different shapes. This results in a smooth, rounded-looking surface on the very top and bottom of the Torus. Now if you fly the camera up really close along the side edge of my Cheap Torus, the illusion might be broken, but at most viewing angles, it looks perfect. You can even fly your camera through the inside of a large glass Torus! The Cheap Torus demo allows you to change the Torus' scale, roatation, hole size, and material. Now we can finally have multiple, air-tight Torii all over our scenes without worrying about precision artifacts or performance costs!

* February 15, 2023: I developed a new custom system for handling large amounts of geometry. For now I’m simply calling it the ‘Shapes BVH’. Rather than dealing with the usual glTF models with their various triangle primitives and vertices, my new system instead builds a BVH (which is an axis-aligned bounding box binary tree) around large amounts of simple primitive shapes like spheres, boxes, cylinders, etc. Using these ray tracing-friendly shapes, we can build up scenes of almost any complexity. Just like traditional triangular models, each small building-shape (primitive) can have its own unique transform (scale, rotation, position) as well as its own material properties. Unlike triangular models, which are, in the end, just an approximation to the original shape/surface, the Shapes BVH scenes are rendered with pixel-perfect accuracy (because they are composed of smaller mathematical, analytic shapes). Certain scenes call for the traditional triangle model/BVH system (like the Stanford Bunny, Stanford Dragon and Damaged Helmet glTF scenes). But other types of scenes requiring a lot of simple primitives don’t really work well with the older triangle BVH system – especially on mobile, where triangle intersection is a performance bottleneck. By using the Shapes BVH instead, now we can have arbitrarily complex and densely populated scenes that can be path traced in real time at 30-60 fps, even on your phone! Better yet, since these scenes are made from simple quadric shapes, you can just call familiar three.js JavaScript commands (like ‘new THREE.SphereGeometry’, ‘new THREE.BoxGeometry’, ‘new THREE.PhysicalMaterial’, and ‘new THREE.Mesh’) to construct any scene you can imagine. To see this new system in action, check out the ‘Invisible Date’, ‘Sphereflake’, and ‘Cube Fractal 3D’ demos. The Sphereflake and Cube Fractal demos both showcase the sheer amount of geometry you can have in a scene, and still have it run smoothly on any device, (even your cell phone!). The Invisible Date scene showcases the different kind of shapes you can use, the various transformations you can do on those shapes, and the various physical material properties you can assign to each and every small shape that is used to build up the final scene.

* January 17th, 2023: New Year - New rendering technique! Major update across the entire repo (and also my path traced games) to how transparent (glass, water, etc) and clearCoat (billiard balls, polished wood, car paint, etc) materials are handled. If you've followed my project from the beginning, you might remember that I have gone back and forth on the technique used to efficiently render objects with these transparent/semi-transparent materials. One way is to use Monte Carlo integration and essentially 'flip a coin' every time a ray encounters a transparent surface. If 'heads', the ray reflects or bounces off of the surface - if 'tails', the ray refracts or transmits through the surface. Using a progressive renderer, this method will eventually converge to the correct result, which is a double-image on the surface. Half of it is the reflection we see, and the other half is the world beyond the surface that we can also see at the same time (think of the double-image you get when looking at a shallow angle through a window). Although this technique works well, the major drawback is that you get 2 noisy images on the transparent surface, due to the Monte Carlo randomization of the rays' path choices. On the other hand, we can do away with the random decisions (and noise), and instead spawn 2 rays when we encounter these transparent surfaces. Although this creates slighty more shader complexity (inside the tight 'bounces' loop), the reward is definitely worth the cost because now we have a smooth, non-noisy, steady double-image appearing on all transparent surfaces. The effect is most noticeable when moving the camera around and looking at these surfaces from different angles. Now you see a reflection perfectly blended with a transmission (or refraction), which more accurately resembles the real world transparent objects that we see every day (and take for granted!). The reason I have returned to this double ray spawning method (1 reflection / 1 transmission ray) after having it the other Monte Carlo way for a year, is that *this* time around, I figured out how to implement it better. Not only does it look smoother and more correct than my previous attempts at this technique, but it is also more performant. Enjoy looking at (and through!) all of the transparent and clearCoat materials! :)
Expand Down

0 comments on commit 8a39a29

Please sign in to comment.