I want to recreate this smoke/cloud effect which is used in the Arrival (2016) movie end credits.

I uploaded a sped up version of the credits to see the smoke dynamics.


http://streamable.com/n3309 49s x6 sped up video of the credits

I know how shaders work and can comfortably implement simple GLSL fragment shaders, but looking at this I can't seem to find a way to get started.

Starting points I considered:

  • Using a noise function: Every noise function I could find looks unnatural and unsmooth. Not what I need.
  • Creating 2D/3D particle simulation: This seems a bit overkill and even then I need functions that do not look calculated.
  • Just use some sprites and transform them randomly around: That's lame and still looks 'fake'.

If you could guide me to a starting point on how to accomplish a somewhat similar looking GLSL shader implementation that would be great!


Noise functions are definitely your friend here—FBM would be one good candidate. You’re right that it can look too uniform on its own, but if you blend multiple layers of it together, using different speeds / directions for each and maybe distorting their domains a bit, you should be able to get very close to the look of that footage. There’s lots of clever uses of noise functions on Shadertoy; for an example of something like the approach described above, check out this one.

  • $\begingroup$ Thank you for the guidance. FBM seems like a suitable noise function to recreate the footage. $\endgroup$ Feb 12 '17 at 11:55

There is good glsl source of noise (simplex noise) online to make real time noise. In addition to this, to make effect of moving fog/smoke like in this video you can make 3D FBM function. This is my function:

float default3DFbm(vec3 P, float frequency, float lacunarity, int octaves, float addition)
    float t = 0.0f;
    float amplitude = 1.0;
    float amplitudeSum = 0.0;
    for(int k = 0; k < octaves; ++k)
        t += min(snoise(P * frequency)+addition, 1.0) * amplitude;
        amplitudeSum += amplitude;
        amplitude *= 0.5;
        frequency *= lacunarity;
    return t/amplitudeSum;

Where snoise is 3D noise function from link and P is used to seed noise, for example

P = vec3(texcoord, uniform_speed)

Where uniform_speed is uniform variable incremented each frame with some value.

  • $\begingroup$ Thank you for the guidance. The codebase you linked and the sample you provided helped me understand and implement my own function. $\endgroup$ Feb 12 '17 at 11:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.