Computer Graphics II - Clouds

 

Third Homework - Volumetric Clouds and Perlin Noise

Hello again everyone, this time we'll be creating volumetric clouds, and deal with procedurally generated 3D noise functions.


However in this blogpost we're keeping things a bit short and technical, since I couldn't find the time to discuss some concepts even though I wanted to do so. Instead, I'll go over the sub-goals of this project and talk about the difficulties I had and how I solved them.


Ray Marching

From the previous homework, I had at my hand a method to draw a quad to screen space directly, which I used also in this homework to draw the plane that is unobstructed by anything else. This means that for now, because I don't use the existing depth buffer, clouds will get drawn over everything basically. However in this homework we didn't have to draw anything else so I didn't bother rendering the frame into an FBO and using its depth buffer, I just closed depth testing for the clouds.

First thing I did was to use the ray directions per fragment, and from the previous homework, they were already implemented. How they work is basically we get the screen space coordinates of each fragment and multiply it by the inverse of view and projection matrices, so we get the looking direction relative to world space. I also passed in the eye position as a uniform so that we can generate the rays. 

For each ray, I sample around 300 points, each point a set distance apart, so that we have multiple points to sample the noise function and accumulate their effect over the ray, resulting in the fragment color.

Generating 3D Perlin Noise

In order to have clouds, we need to simulate the density of clouds given a 3D environment. I have directly used the perlin definition given in the pdfs, but they turned out to be somewhat faulty, so I changed it a bit. I think the random table was wrong, so I changed it with a permutation array, so each point still gave response to a stable noise, but it was randomized in a better fashion, eliminating patterns.


I also overlaid multiple frequencies on top of each other to better simulate the cloud texture.
 
One another method I used was to scale the positive side of the noise function by a factor of around 20, then divided it so the range was still from 0 to 1, so in effect that made the clouds get separated because now the 3D noise had a lot of gaps where it responded below 0.

Rendering Clouds

I'm very happy about the clouds, since I'm using the emittance model, which is supposed to be very basic. The way I simulate density however, I have a trick up my sleeve, While sampling the points, I change the cloud color according to the current density of the sampling point, resulting in gray areas for the insides of the cloud, which gives a lot of pizazz. 
 


I have forgot to re-adjust the coordinates of the clouds of multiple frequencies, but that also created a great visual. In the following picture you can see that the low frequencies were on top of the smaller ones, creating a really cool cloud:

Fly Controls

In order to fly and turn appropriately, we needed rotations, and quaternions were the way to go. Let me tell you something, I had a very hard time understanding quaternions, but upon thinking about it a long time, I had a very sudden realization on the simplicity of quaternions, which made me really happy as an individual because they always seemed like magic.

In order to use quaternions, I store the current orientation of the "plane" as a quaternion. Then if I want to, say roll over the relative forward axis, I first turn the forward axis by this orientation quaternion, which gives me the rotational axis. Then I simply construct another rotation quaternion and multiply the orientation quaternion. At each frame, I use the orientation quaternion to find the model matrix for the looking direction.

Flying just below the lower point of clouds, seems like fog.

Optimizations

Ray marching was very slow, so I thought some methods to deal with it. The first realization I had was that the clouds only spanned a section of the y coordinate, so that meant that when a ray that used to be in the cloud range was now wasn't, we no longer had to continue sampling because we were past the cloud range. However, it later turned to another solution where I moved the ray as close to the cloud layer as possible, and only then started to sample the clouds. This also caused very far clouds to be rendered, since 300 points were rendered starting from that location.

I also switched from using the function f defined in the pdfs to simply using OpenGL smoothstep function, which approximately did the same trick.

Happy Accidents

Here are some of the results I had, which I wanted to share with you. You can see that I had a lot of fun during these:















 
That concludes this last homework for this semester! See you in the final projects..


Yorumlar

Bu blogdaki popüler yayınlar

Computer Graphics II - HDR & Physically Based Rendering & Image Based Lighting & Shadows

Computer Graphics II - Bezier Surfaces