My Snow Simulation

 Welcome to my last blog for our course CENG469 Computer Graphics 2!


This blog will be about our final project which we chose the subject ourselves. 

I chose to simulate a falling snow and its accumulation on ground as I am in the end a winter child and also wanted to create something I encounter while playing my favourite games.

I implemented a particle system to simulate the falling snow and used displacement map to show the accumulation. I will again explain my implementation step by step.

Snow Particles

First step was generating the snow particles. To do this I implemented a snowflake struct which has the necessary attributes position, size, velocity and direction vector. In every frame, I created a new snowflake with random attributes and erased them when they hit the ground. Also I added and normalized their direction vector with another random vector to create the chaotic movement of snow fall.

struct Snowflake{
Snowflake(glm::vec3 p, glm::vec3 d, float s, float v): position(p), size(s), velocity(v), d(d) {}
glm::vec3 d;
glm::vec3 position;
float size;
float velocity;
};

Rendering of snow particles

To render this particles, I have used textured quads and a texture with a white circle. The tricky part here was wherever the camera is we want the snow particles to face the camera so that all of them can be seen clearly regardless of the position of the camera. To do this, I used something called the billboarding effect. Basically, you rotate your quad to face the camera at every time. The code may look tricky but it is actually a simple solution to our problem.  Result can be seen in video below.

    glm::mat4 inverseViewMatrix = glm::inverse(viewing);
glm::mat3 cameraOrientationMatrix = glm::mat3(inverseViewMatrix);
glm::mat4 modelMatrix = glm::mat4(1.0f); // Identity matrix
glm::mat3 quadOrientationMatrix = glm::mat3(modelMatrix);
glm::mat3 billboardOrientationMatrix = cameraOrientationMatrix * quadOrientationMatrix;
modelMatrix = glm::mat4(billboardOrientationMatrix);



Accumulation of Snow on Ground

The most difficult part for me was implementing the accumulation of snow. Upon our professor's suggestion, I decided to use displacement maps to create the effect of snow accumulation of the ground.
To do this I first created a 512x512 displacement map texture and bound it to a snow height data array which is initially zero.

glGenTextures(1, &displacementMapTexture);
glBindTexture(GL_TEXTURE_2D, displacementMapTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, textureWidth, textureHeight, 0, GL_RED, GL_UNSIGNED_BYTE, snowHeightData);

Whenever a snow particle falls on the ground the corresponding value on the array is updated until it reaches 255.

Then on the vertex shader according to the texture coordinates of the ground mesh the new height of the vertex is found.

float displacement = texture(displacementMap, aTexCoord).r;
vec3 displacedPosition = aPosition + vec3(0.0, displacement * displacementScale, 0.0);

I spent so many hours at this point because the mesh I was using for the ground was 1x1 quad and when the snow accumulation started all of the ground would start levitating. To solve this I found another quad obj which has 36x36 vertices which of course worked better. A quad with even more vertices would produce a smoother result. However, I could not find one.

In the fragment shader I implemented diffuse lighting with a snow ground texture to create an aesthetically pleasing effect. To see the accumulation better here is a video of snows falling on a limited area:

It looks kind of salty but you get the point. 

Bunnies to feel at North Pole (also a dwarf)

Lastly, I scattered some bunny objects in the scene so that the viewer can feel the accumulation better by watching them. I also applied lighting to them to be one with the scene.
End result can be seen below :)





I would also like to be able to accumulate the snow on this bunnies but that would require mesh particle collision which would be harder to implement and could decrease the frame rate drastically.

In the end I am happy with my result and it was a very fun and educative experience.
Thanks for everything,
Zeynep Su Yalçın

Comments

Popular posts from this blog

Surface Rendering with Bezier Surfaces

Quaternions and Procedural Noise