Skip to content

Commit

Permalink
Glass, transparent, & clearcoat objects are now virtually noise-free!
Browse files Browse the repository at this point in the history
  • Loading branch information
erichlof authored Sep 12, 2024
1 parent b1055d9 commit 9435b53
Showing 1 changed file with 2 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,8 @@ A technical note about what you are seeing: The data arrives to the fragment sha

<h2>Updates</h2>

* September 12, 2024: Now all glass and ClearCoat surfaces are noise-free! In the recent past, I improved my technique for rendering smooth, transparent surfaces containing both reflections and refractions. However, I didn't understand at the time how to handle both the reflected image and the refracted (or transmitted) image underneath (think glass sphere), as far as the de-noiser is concerned. The de-noiser requires accurate information across groups of pixels so that it can first determine where the edges are (between objects, or between surfaces with differing normals), and then it can keep those boundary edges sharp while blurring the noisy diffuse part that is uniform across the objects. Since my de-noising scheme was unable to resolve the double images (reflection vs. refraction underneath), I had simply side-stepped the issue and made the whole glass object slightly noisy and blurry. This worked ok I guess, but I was never happy with it. But over the summer, I went back to this problem, and approached it with new, fresh eyes. I realized that I could delay parts of my de-noiser, based on where the rays were in the tight 'bounces' loop. In a nutshell, I leave the de-noiser on for the 1st bounce (initial raycast from the camera), so that it sees and detects all of the boundaries of objects against the background sky (or against background walls of a room), and also boundaries between different objects. Then if the ray tracer encounters a glass sphere for example, I wait until the refracted rays have passed all the way through the sphere and behind the sphere - then I turn on the de-noiser again, which once more checks for edges to keep sharp and diffuse noisy surfaces to blur. Then, for the reflected portion (on the outside of the sphere), I once more turn on the de-noiser and check for edges out in the scene that must remain sharp. So essentially, transparent surfaces are de-noised three times within the same tight bounces loop. The result is a much sharper and crisp refracted image (that is often upside down in glass spheres, or severely bent due to the refractive index), as well as a cleaner, sharper reflected image on top of that. To see this latest technique in action, check out my 'Geometry Showcase' and 'Quadric Geometry Showcase' demos. Try moving and rotating the camera around, all while staring at the glass sphere (and other glass objects). Also, try flying the camera inside the glass sphere and looking at your surroundings through the thick glass. I think you'll be pleased by how smooth, crisp, and virtually noise-free these surfaces are now! :)

* 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.
Expand Down

0 comments on commit 9435b53

Please sign in to comment.