Oskar Schramm Portfolio

Volumetric Clouds.

As a graphics programmer, I have always been intrigued by the impact of volumetric rendering in computer graphics. When given the chance to work on a project, I decided to focus on creating realistic and dynamic cumulus clouds. After conducting extensive research and experiments, I developed an efficient rendering method that not only produced visually stunning results, but also achieved high performance.
  • Combined 3D Worley Noise generated with compute shaders
  • Ray March Through Volumes
  • Anisotropic Scattering using various Phase Functions
  • Performance optimizations by varying raymarch

Goals.

The Goals of this project:
  • Expand my expertise in volumetric pipelines and delve deeper into the rendering of real-time realistic clouds.
  • Experiement with various performance optimization techniques, especially when performing raymarching.
  • Enhance performance and efficiiency to allow incorporation of other related techniques such as volumetric lighting.
 

Challanges.

During the implementation, there were several challenges that needed to be overcome such as finding the right balance between visual quality and performance, as well as ensuring the clouds looked consistent and natural across different viewing angles and lighting conditions.
Some of the challenges which I encountered were:
  • Incorporating volumetric shapes into the pipeline proved to be challanging due to the fact that we had never previously required then in any of our projects, thus presenting an obstacle in the architecture setup.
  • Creating the 3D texture due to inexpererience in the texture generation area.
  • Incorporating the 3D generation to Compute Shaders, since I was not very confident with them yet.
  • Achieving the desired “silver lining” effect towards the sun.
Despite the obstacles, I managed to develop a volumetric cloud system that elevated the scene’s level of immersion and depth. This experience not only provided me with insight into volumes, but also enabled me to gain a deeper understanding of lighting, 3D textures, raymarching, and performance optimizations.
correctvolume
noiseCube

Implementation.

After doing some research I foudn some great resources which would lead me in the correct direction. Based on the information gathered, my proposed implementation would include:
  • Ray vs Volume intersection to get the distance of the volume.
  • Raymarch through the volume and apply Beers Law at each sample point.
  • Raymarch towards the sun at each sample point, and again, sample from the 3D texture.
  • Generating and using a 3D texture based on Worley Noise.
  • Implementing a Phase function to get proper light scattering.

The Architecture

Initially, I focused on establishing a suitable architecture to support the implementation of volumes for the volumetric clouds. I referred to a video demonstrating how other game engines render clouds and experimented with various methods to transfer all the required data to the GPU.
Once I obtained the correct world space axis-aligned bounding box (AABB) from the volume, I conducted a ray vs volume intersection to determine the ray’s entry and exit points. By subtracting the entry and exit points, I obtained the distance and applied the Beer’s Law equation to achieve a partially transparent volume-like appearance.

Generation of the 3D texture

I initially planned to continue with raymarching through the volume towards the sun, but I decided to change my approach for more immediate visual feedback. Instead, I started with generating a 3D texture using a compute shader that wrote the distance to the nearest point for every dispatch, resulting in Worley noise.
Although the tiling did not work correctly, I used a simple solution of generating the texture 27 times, similar to a Rubik’s cube. Since the generation only occurred once, performance was not a concern, allowing me to focus my efforts elsewhere. However, since I had not worked with 3D textures before, I needed to make many small adjustments to get both the generation and sampling to function correctly. Fortunately, I received a lot of assistance from a Graphics Programming Discord channel.
cubesofcubes
256×256 (left) & 64×64(right) textures with 3 different seeds of Worley noise generation combined (Worley is a noise based on Voronoi)

Raymarching – Ray vs Volume

Now that the noise was created, it was time to add on to the previous ray vs volume intersection shading. With the distance between the intersection points and having the editor tools to adjust raymarching steps, I could easily figure out how many steps needed to be taken and how long they should be. For every step, I sample from the 3D texture to see if there is any matter there. I then add all of the accumulated density together and once again, apply Beers Law to it.
particlePicture

Proper Lighting

After raymarching towards the sun, we again sample noise and apply light through a phase function for volume particles. The phase function helps determine how light is scattered at different wavelengths in the volume. It’s like the ambient and diffuse reflection of surfaces, where some light is scattered randomly (ambient) and some by a perfect reflection (specular/forward scattering).
To achieve realistic light scattering, I used the Henyey Greenstein phase function for volume and a function from Pixar’s Wizard Of Oz.
Proper ‘Silver Lining’ effect towards the Sun using Henyey Greenstein Phase Function
Raymarching towards the sun proved more challenging than expected, as errors in lighting, transmittance, and ray scattering were prone to occur and took some time to fix. At this time I also extended the implementation to support distance-based fog.
silverLIningWorking
Proper ‘Silver Lining’ effect towards the Sun, using Henyey Greenstein Phase Function
fogPicture
Applying Distance/Height-based fog

Optimizations.

Regarding the optimizations, I delved deeper into several research papers that discussed different approaches to improve performance. Initially, I explored signed distance fields and eventually developed a hybrid solution that incorporates multiple methods.

My solution – Variance Ray Marching

Initially, I began integrating signed distance fields into the volume calculation, drawing from insights provided in this particular article. However, I was unable to complete this task due to time constraints. Subsequently, I re-evaluated my strategy and conducted additional research.
After reviewing another article’s optimization section, I became convinced that adjusting step lengths based on collision detection and subsequently refining the details with a more precise step size through backtracking would be an effective approach. Incorporating these changes into the code, along with some additional minor optimizations and the inclusion of horizon-based length calculation, would provide me with satisfactory performance.
The optimized version using my solution above. Almost doubles the framerate.
(128 volume & 32 light rays), (128×128 highres & 32×32 lowres noise textures)
Default Solution: ~16ms
My Optimized Solution: ~8ms

Summary and Future Work.

The most significant lesson I’ve learned from this project is how to integrate all the components to create a finished product. While many aspects of the project weren’t entirely unfamiliar, consolidating them into a cohesive whole presented a unique challenge. Additionally, I’ve gained extensive experience in GPU debugging using tools such as RenderDoc, and my knowledge of lighting has expanded as well.
As a graphics programmer, I am always looking for new and exciting ways to push the limits of visual technology. For me, integrating a cloud system with other game systems like lighting and particles would not only enhance the overall aesthetic of the game but also showcase the potential for advanced graphics programming techniques. It’s a challenge that I am eager to take on and I believe it will greatly enhance the player’s immersive experience.
Some things I would like to continue on are:
  • Making the optimized clouds more visually pleasing
  • Clouds read from the depth and fade depending on distance to nearest object
  • Clouds write to the shadow map to enable casting of volumetric light
  • Integrate the cloud system with other game systems (e.g. lighting, particles)
  • Weight texture that can be customized by artists to determine the location of clouds for more cinematic control