How Do You Use a Shader to Create Clouds in three.js?

There are many examples of shaders that display screens full of animated clouds and/or waves. I would like to include this kind of effect in a three.js scene. However, the three.js programs I have found use shaders only to create textures for objects - which I don’t think is what I want to do.
One example that comes close to what I want is on the webpage for Kevin Roast:
It uses some elements of three.js, but not the main library. It displays the results on a canvas, but does not display them in a three.js scene or use a three.js camera (one appears to be built into the vertex shader at line 670).
The code where the shaders are complied and linked into the program is at lines 830 to 883.
Can I link a shader into a three.js scene? Or should I define it as a texture and display in on an object, like a flat plane?

This is actually the usual way of creating clouds. It also called viewpoint-oriented billboards and explained in the book “Real-Time Rendering (Third edition)” in chapter 10.6 “Billboarding”.

You can create custom shader with ShaderMaterial or RawShaderMaterial. The first of the two provides some built-in uniforms and attributes that are usually necessary for shader development. If you want to start from scratch, use RawShaderMaterial.

In any event, I don’t think the presented demo is very useful in a typical 3D application. The ocean scene is rendered on a flat 2D plane based on ray marching. Compared to this ocean example, it’s not possible to use it together with a scene graph containing 3D objects like character models.

I would say it’s more or less a pure rendering demo. The code itself is not useful when working with a three.js scene graph.

I have a question regarding the stats. How come I have 10 fps in that ocean demo, and yet it shows that the scene takes 0-1ms to render? Is it because the CPU is the bottleneck and the MS meter monitors only GPU activity or something else? I’ve noticed this in many of my apps as well :thinking:

One possible and popular technique is to use seamless noise (generated or from a preloaded texture) to indicate where to use the sky color and where to use the clouds color on your sky geometry object, mixing them into a pleasing view. Then, in the shader, you could move the uvs with a time uniform to make the clouds “move”. You could use more than one transparent sky layers to get more details/interesting visuals.

Are you talking about stats.js? If so, the time values are computed with JavaScript via the performance API or Date (fallback) and represent the overall time for computing a single frame. Not sure why it does not work on your computer…

You can use raymarched elements with a regular scene, though it needs optimizations like bound to volumes and upscaling.

You see it in engines like Unreal and Unity too for some effects like volumetric clouds and fog, i’ve implemented volumetric impostors recently, with the same technique i’m experimenting with volumetric clouds.

But this is a more expensive approach and unless in your game you don’t fly in the sky i would rather recommend a cheaper approach. Some tradeoff would be soft-particles still giving a volumetric effect, but i wouldn’t recommend billboards only, they won’t appear volumetric and you’ll see planes sticking through each other.

From ground view one approach is using a plane with layers of flat clouds, the pros are that it’s cheap, looks good enough and you can even use it for cheap shadowing and weather effects like where it rains.

1 Like

My statement referred to the particular shader code from the demo. Not to ray marching in general.

It could be used, though not just some plug and play manner, it needs some work, know how and depends on how efficient it is, but the clouds don’t look too expensive, the most impressive i’ve seen yet was one that implemented those of horizon zero dawn.

I think the “billboard” method is the method I used in an example I posted to this forum of an aircraft flying in an undercast of clouds. The undercast was composed of groups of identical transparent pixels.

With shaders, the current preferred approach to making clouds appears to be to use ray marching. So I was hoping to incorporate a small shader-driven undercast of clouds in a three.js scene with a skybox and a detailed object. But it sounds like that might not be feasible or perform well.

(On the shader example posted, I am only interested in the cloud effect. So I was going to have to edit out all the effects relating to the water - which could be quite a challenge.)


You may have seen it, but the people who created the Horizon Zero Dawn clouds prepared an extensive presentation explaining how they did it. One of their challenges was to go beyond the flat undercast clouds into the world of fluffy cumulus clouds. I was hoping to just get to the flat undercast clouds. I believe they settled on using a raymarching approach.

Ideally, I would like to have an environment like that in War Thunder, which does a pretty good job of combining airplanes and clouds in a 3D environment. But I would be willing to settle for a fixed skybox background instead of an open world environment.