Leveling Up Raven: BVH, Transformations, and Instancing
“The enigmatic duo David’s Reflection has captivated audiences with their unique fusion of classical and modern sounds, and now, they’re set to release their highly anticipated album, Gaze of Eternity. Known for their haunting melodies and introspective lyrics, David’s Reflection draws inspiration from the iconic duality of Michelangelo’s David, embodied by the two statues staring forward on the album cover. Gaze of Eternity delves into themes of identity, introspection, and timeless beauty, capturing a soundscape where ancient echoes meet contemporary beats. Fans of art rock and atmospheric pop alike will find themselves immersed in a world where music reflects the tension and harmony of looking both inward and outward, balancing tradition with innovation. This album promises to be a soulful journey, one that resonates with those who are unafraid to confront their own reflections and the art that shapes them.” (generated by gpt4)
(I wanted to make funny opening since the image looks like a music album cover. I thought that it might me a good idea to put a short story about them. 😄).
|
Introduction
Glaring David Scene rendered in 350ms with BVH and 16 Threads |
Hi everyone, welcome to the second blog of my ray tracing
journey. In this assignment, I implemented BVH (Bounding Volume Hierarchy) as an
acceleration structure for Raven. Then, I implemented geometric
transformations, and instancing features for Raven. These features will help us
to create and render much more complex scenes.
Implementation
I created BBox and BVH classes for the BVH part. Also, I created Transformation class for doing transformations part. Lastly, I created MeshInstance class for dealing with Instancing feature.
- BVH:
- In Raven, scenes contain a Bounding Volume Hierarchy (BVH) for all meshes, primitive triangle, and spheres based on their axis-aligned bounding boxes (AABB).
- Each mesh also has its own BVH constructed from the triangles that make up the mesh.
- To generate the BVH, I split the AABB in the middle along the current dimension and alternate the dimension at each level in the order of x, y, and z. I consulted Peter Shirleys’ Fundamentals of Computer Graphics Book (Chapter 12 page 304) when I implemented BVH part.
- Transformation:
- If a Mesh Instance, primitive triangle, or sphere has any transformation information, I apply the transformation to their bounding boxes to maintain the order of BVH.
- Once I parse the scene, and the shapes have transformation, in the consctruction part, I created a transformation matrix according to given transformation type (Translation, Scale, or Rotation), I pre-calculated inverse and inverse transpose of transformation matrix for optimization purposes.
- Instancing:
- For this part, MeshInstace class has its own Transformation and BBox information. Also, It stores base mesh's pointer so that I can make transformation without affecting base mesh information.
- For Intersections:
- Mesh Instances, Triangles and spheres convert the coming ray into their local space by multiplying inverse transformation matrix, and check if there is intersection.
- When there is an intersection, the shape normal is transformed by inverse transpose of transformation matrix.
Another Davids Scene rendered in 352ms with BVH and 16 Threads |
Marching Dragon Scene rendered in 1217ms with BVH and 16 Threads. (I changed the color order of the original scene btw) |
Issues
As usual I faced many problems while I implementing Raven for this assignement. I list and explain them briefly.
- The first bug that I faced when I was dealing with Transformation part. I tried to render ellipsoids scene but couldn't achive successfully. The problem is that I didn't pay attention to glm math library's matrix casting. When I want to cast mat4 to vec3 format, I thought it will cast implicitly however I didn't achive the result. I had to cast explicitly. This issue took my one day to figure out.
- The issue involves incorrectly calculating the normal transformation matrix. Normally, I take the tranformation matrix and do inverse and transpose operation. It didn't work however, when I use inverseTranspose() function in glm, it was solved. I don't know what the main problem is but probably this is due to glm version.
Normal Transformation Problem |
- This one is a bit tricky because I spent three days to solve this issue. The problem occured when I use MeshInstance. I had a problem with calculating transformation matrix for MeshInstance. When I get MeshInstance transformation matrix, I multiply with Base Mesh transformation. However, when I first multiply MeshInstance transformation matrix with Identity matrix and then multiply with Base Mesh transformation matrix, the isssue was solved.
MeshInstance Tranformation Problem |
- I think that this one is an embrassing issue that I faced in this assignement. Because, when I parse MeshInstance, for somehow, I parse its material wrongly. Then, it was just parsing for one material. The problem is that I had to use "NextSiblingElement" instead of "FirstChildElement.
Optimization
Since I don't have enough time to improve my codebase, I did one optimization trick for my Transformation class. Once it get the transformation matrix, it automatically calculates inverse and inverse transpose of itself.
I found some optimization ideas and I will do in my third assignment. Here's the list
- For Ray class, I will pre-calculate inverse direction.
- I will use this optimization trick for bbox intersection.
- I didn’t find time to implement Möller-Trumbore Triangle Intersection. (As I said for second assigment but I will do it in third assignemnt.👌)
Benchmarks
Here's some
scene benchmarks for BVH and non-BVH settings.
System Specs:
CPU: AMD
Ryzen 7 5800X, 8-Core/16 Threads, Max Freq 4.7GHz, 36MB Cache
Memory: 64 GB 3600MHz DDR4 RAM
Comments
Post a Comment