Realistic, animated clouds

Because the weather where I live is what it is, I had ample opportunities to look at clouds this summer and I figured I should make some nice clouds for Panda3D.

Here’s the code:
github.com/wezu/cloud/

Here’s a screen:

And here’s me talking about it:

There’s a texture atlas with 28 cloud images. There’s also a shader that takes two images from the atlas and blends them from on image to the other over a period of time, and then moves on. It’s done the same way that texture atlases work for particle animation, but with the added blend between frames. I had to make it this way because clouds change very slowly, if I made a frame-by-frame animation it would need a few thousand frames.
Procedural generated clouds either look fake, are insanely complex or both.

The rest is simple. Each cloud is a point-eye billboard with a fade lod node (so they do not pop out of nowhere), they are all just moving in one direction.

I think the code is simple and clear, if it’s not - ask.

What could be improved? I imagine the clouds could be instanced, but I have no idea how to rotate them to face the camera in the shader in that scenario.

Code is free, the cloud atlas is CC-BY-SA (contact me if you want it on some other license).

It looks as though a model is missing from the linked repository: attempting to run the program produces the error “IOError: Could not load model file(s): [‘cloud’]”, pointing to line 12 of cloud.py.

However, going by the screenshots and description, this looks rather good–and thank you for sharing it! :slight_smile:

As to improvements, I’m not sure; perhaps creating clouds not as single quads (if I’m understanding the system correctly) but as clusters of your current cloud models in order to emulate the varied shapes of natural clouds.

Otherwise, have you ever experimented with clouds based on 3D perlin noise? I seem to recall seeing some decent results from such approaches. What I’m imagining is something along the lines of using a shader for the sky itself, then using a 3D perlin noise function to render the sky, shifting the system’s coordinates in the first two dimensions to produce drift through the sky, and in the third dimension to produce the shifting forms of the clouds that you’re producing via fading. Admittedly this is more complex than your solution, and I’m not at all sure of how well it might perform.

Ah, the missing egg. My git client has a default ignore list that has .egg on it (thinking it’s a python-egg).
I’ll fix that when I get home.

The position of the clouds gets randomized at the start so they form clusters automatic (with some luck)

I’ve experimented with 2d noise and got the kind of clouds you had in Doom2 or Quake1 at best

Fixed the missing models.
github.com/wezu/cloud

Ah, it works now! I like it. :slight_smile:

Hence, to some degree, my suggestion of 3D noise rather than 2D. :stuck_out_tongue:

I might have a shot at putting together a quick prototype; I’m not terribly familiar with shaders, however, so I may not get it working. ^^;

To some degree, yes, but I find that they don’t cluster all that often, resulting in the clouds tending to have more or less the same shape.

I messed around with the code a little in order to produce intentional clumping; I’m not sure that it’s an improvement (I’ve seen some occasional flickering that I imagine results from transparency layering issues, for example), but take a look. The changes are as follows (each change should be marked with a comment, although I may have missed some):

        # I placed the clouds a little higher in order to be able to better see them
        self.cloud_z=30
        self.cloud_speed=0.3
        cloud_size=5

        # Lots of clouds! :D
        cloud_count=80
        self.clouds=[]

        for i in range(cloud_count):

            # For each cloud, randomly determine how many parts it has
            numClouds = random.randint(1, 7) 

            #  The position of the cloud, copied from your original "setPos" call,
            # if I recall correctly; I'm planning on using it more than once
            # below, and hence am generating and storing it here.
            basePos = Vec3(random.randrange(-self.cloud_x/2, self.cloud_x/2),
                                   random.randrange(-self.cloud_y/2,self.cloud_y/2), 
                                   random.randrange(self.cloud_z)+self.cloud_z)

            #  The more parts a cloud has, the smaller those parts should be,
            # in order to prevent multi-part clouds from becoming too large
            cloudScale = cloud_size*0.7/numClouds + cloud_size*0.3

            #  Now, iteratively generate cloud-parts. This is essentially
            # the previous cloud-generation code.
            for i in xrange(numClouds):

                #  Generate offset values for scale and position,
                # vary the size and place of each part
                scaleOffset = random.uniform(-cloudScale*0.4, cloudScale*0.4)
                x = random.uniform(cloudScale*0.5, cloudScale*1.2)*random.choice([1, -1])
                y = random.uniform(cloudScale*0.5, cloudScale*1.2)*random.choice([1, -1])
                z = random.uniform(cloudScale*0.1, cloudScale*0.2)*random.choice([1, -1])
                posOffset = Vec3(x, y, z)

                self.clouds.append(cloud.copyTo(self.cloud_root))    
                #  Set position and scale, using the offsets 
                # produced previously, and additionally apply
                # a random rotation to further vary the shapes
                # produced. I'm not sure of how I feel about
                # the rotations, however.
                self.clouds[-1].setPos(render,basePos + posOffset)
                self.clouds[-1].setR(random.uniform(0, 360))
                self.clouds[-1].setScale(cloudScale + scaleOffset+random.random(),
                                     cloudScale + scaleOffset+random.random(),
                                     cloudScale + scaleOffset+random.random())

It’s interesting, but the tilted clouds don’t look good :stuck_out_tongue:

This is a photo I took today and most of the clouds have a similar form (like a sort-of-a-blob or a legless sheep)

I think the best way to have clouds of different shape is to make a new cloud atlas for that.

I’m kind of tempted to generate a normal map from the textures and see if I can get the clouds lit, if that won’t work I have another idea, that’s crazy enough that it could work. I’ll share the code if any of it is worth looking at :mrgreen:

You’re probably right on that. ^^;

Eh, to my eye they’re quite variable–or at least more so than in the non-clump-generating version of your code.

That would help, but I suspect that the limited number of shapes would still make for a little too much repetition.

I look forward to seeing what you have in mind! :slight_smile:

I thought that I should post a quick update on my experiments with noise-based clouds:

In short, it didn’t go as well as I’d hoped, although I’m not entirely unhappy, especially for my first shader (albeit building on Wezu’s shader). I still think that the technique holds promise, but I’m not managing to get to a point that I quite find satisfactory (at least in part, I think, as a result of my inexperience with shaders). Given that this is distracting me from my main project, I intend to set it aside.

Here are a few screenshots of the latest iteration of my noise-based clouds:
(The barred recatangle towards the top-left displays the image that I generate for the purpose of pseudorandom-number sampling in the shader; it can be safely ignored. ^^; )

[edit]
One element that I forgot to mention, and that isn’t visible in the screenshots, is the use of 3D noise instead of 2D, in order to produce a slow evolution in the clouds rendered. This I found to actually work rather well–in fact, it’s one of the elements that I’m most happy with, I feel.
[/edit]

Looking towards the horizon:

Looking more-or-less upwards:

The shapes of your clouds are very good, but they are too sharp, a bit of blur and that could be really good.

I’ve added a simple water shader to the repository, not sure why, but somehow clouds+sea work together well (or maybe it’s just the vacation-summer-fever talking…)

The code is still here:
github.com/wezu/cloud/

Ooh, the combination of clouds and reflecting sea really does look lovely. :slight_smile:

Thank you. :slight_smile:

Heh, yes, I noticed their over-sharpness when comparing yours to mine, as I recall. ^^;

However, for now (even aside from having another project to work on) I’m a little sick of wrestling with random numbers in shaders, so they’ll stand as they are for the moment. ^^;

Nice work! A glsl version would be nice.