Introduction

As I mentioned in my post on god rays, I’ve been focusing my time recently on environmental weather effects. The end goal being a weather system for my game that can dynamically transition between different weather patterns. This could be used for creating transitions in weather between different regions or just base on the time of day.

Today I want to cover an approach to adding shadows for our clouds. What about making actual clouds you might ask? Well since The Far Reaches is a top-down game, the camera is never actually pointed at the clouds.

It doesn’t really make sense to render clouds if we never see them so let’s instead focus on how they affect the world around them. The main way that clouds impact our scene is shadows. Let’s dive into a procedural approach to creating these shadows!

Cloud Silhouette

I think a reasonable start is to first create a silhouette of our clouds. We’re going to achieve this with noise. Luckily Godot provides a noise texture we can sample to create our clouds from.

Caption

Godot’s Perlin Noise

This, unfortunately, looks more like a stormy day with high cloud cover. We want to be able to control how much cloud cover there is. Since the image can be treated as black-and-white pixels in the range of 0 to 1 let’s try setting all pixels above a certain cutoff value to white and the rest to black.

Caption

Varied Cutoff values

Varying that cutoff makes the black take up more or less space in the texture depending. We can still improve this a little. Playing around with some parameters for the built-in noise texture gets us:

Caption

There’s definitely room for improvement in the shape of the clouds but for now we’ll make do with these shapes for our silhouette.

Sampling the Silhouette

Okay now that we have the silhouette of our shadows how do we actually check to see if a point on surface is in our shadow. Let’s first look at a two-dimensional version of this problem:

Caption

Shadow Casting

Here we see three distinct layers:

  • Clouds The point above us where our clouds exist. We are treating this as a flat plane.
  • Origin Where the world’s y-coordinate is 0. This could potentially be the same as whatever surface we are casting shadows on..
  • Surface The surface we are trying to cast shadows on. Shown as flat for simplicity’s sake.

In order to check if a point on the surface layer is shadowed by a cloud we can cast a ray in the opposite direction of the sun direction and see where it intersects with the cloud layer. The point at which it intersects is where we want to sample. Notice that in order for this to work we define a height h above the origin layer we want our cloud layer to be.

Now that we know how to sample our clouds’ shadows at any point in the scene. We can use this function in our various shaders to actually cast shadows on our objects. The way this works is a bit in the weeds but put simply: when calculating the impact of each light on each pixel of the screen, we also take into account whether or not that pixel is in the clouds’ shadows.

The result is pretty cool but as always, I think we can do a little better.

Caption

Cloud Shadows!

Softer Edges

Developer Disclaimer

My game’s rendering utilizes a far bit of custom lighting such as dithering between brightness levels. This means that if you’re following along, some of my rendered scenes may appear slightly different from yours.

My first complaint is the hard edges on our shadows. Let’s fix this by creating a region between our 1s and 0s in our noise texture that smoothly gradients between them.

Now our shadows are looking a lot softer.

Caption

Softer Shadows

Roiling and Moving Clouds

Okay I really just wanted to use the word roil if I’m being honest.

What I’m referring to is the nature of clouds to slowly change shape over time. This turbulent behavior is usually caused by winds pushing on the clouds. And speaking of wind, we should let the clouds move as well.

Roiling

Let’s talk about how we can make the clouds roil (see its a really good word). This seems like it would be really hard to achieve with our two-dimensional noise texture. Good thing there’s a such as three-dimensional noise!

If two-dimensional noise changes in the x and y directions then its safe to assume that three-dimensional noise changes in the x, y and z direction. So let’s just replace our 2D noise with 3D noise and try slowly moving through our noise’s z dimension with time!

This looks pretty good already!

Caption

Roiling Clouds

Moving

Moving the clouds is as easy as simply defining a direction we want the wind to be blowing our clouds and moving our noise texture’s sample point in that direction.


Putting everything we’ve discussed together and we get a pretty neat effect. The clouds affect both the god rays and the surfaces they pass over!

Caption

Full Cloud Shadows

Conclusion

I hope you enjoyed this short excursion into the world of procedural generation. There’s many improvements that could be done to make these clouds seem more realistic. For now I think these stylized clouds will serve The Far Reaches very well. Although in the future I may attempt to improve them.

As always please leave a comment below if anything was confusing or if I got some information wrong so I can clarify / correct any mistakes. Also feel free to let me know what you think, offer advice or tell me what topics you’d like me to try to tackle!

Take care and see you soon!

— Carson

Resources