Skip to content
Sample of Volumetric Clouds from Cellular + FBM

shader_legends_3 · BigWingsClouds

Volumetric Clouds from Cellular + FBM

A painterly cumulus-cloud sky built from a Worley/cellular noise layer (cloud puffs) gated by a low-frequency FBM (large-scale cloud coverage) and a high-frequency FBM (in-cloud detail). The combined field is smoothstepped into a coverage mask, then composited over a sky-blue gradient and lit vertically (darker at the base, brighter at the top) with a warm sun-glow tint near the upper-right. The result is a recognisable 'clouds seen from above' scene built from three different noise primitives.

Original: https://www.shadertoy.com/results?query=bigwings+clouds

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
shader_legends_3
Source
shader_legends_3
Evolution
cellular
Render
layered_field
Complexity
medium
Agents
0
Year
2017
Author
Martijn 'BigWings' Steinrucken (Shadertoy user 'bigwings')

Math essence

f = (1 - cellular_2d(uv)) * (0.6 + 0.5 * fbm(uv, 4 octaves)) + 0.5 * fbm(uv * scale_detail, 3 octaves) * (1 - cellular_2d(uv)). coverage = smoothstep(coverage_low, coverage_high, f). col = lerp(sky, cloud_base + (cloud_top - cloud_base) * lighting(y), coverage) + sun_color * exp(-sun_dist * 2) * 0.20.

Parameters

Name Type Default Range Description
dim int 400 160–800 Square output size in pixels.
cloud_scale float 3.5 1–12 Worley/cellular sample rate.
detail_scale float 11 4–30 High-frequency detail FBM rate.
large_octaves int 4 2–7 FBM octaves for the large-scale coverage layer.
detail_octaves int 3 1–5 FBM octaves for the in-cloud detail layer.
coverage_low float 0.42 0.2–0.65 Lower bound of the smoothstep coverage mask.
coverage_high float 0.92 0.65–0.99 Upper bound of the smoothstep coverage mask.
sky_color rgb 0.45,0.65,0.85 null–null Sky base colour.
cloud_base rgb 0.65,0.65,0.7 null–null Cloud colour at the base.
cloud_top rgb 1,1,1 null–null Cloud colour at the top.
sun_color rgb 1,0.9,0.65 null–null Sun-glow tint.
sun_x float 0.72 0–1 Sun x position in canvas units.
sun_y float 0.3 0–1 Sun y position in canvas units.
drift float 0.03 -0.3–0.3 Per-step drift of all noise samples (cloud motion).

Reference

First 60 lines of reference.py. Full source: library_external/shader_legends_3/BigWingsClouds/reference.py

from __future__ import annotations

from typing import ClassVar

import numpy as np


def _hash22(x: np.ndarray, y: np.ndarray, seed: int) -> tuple[np.ndarray, np.ndarray]:
    """Two-component hash from integer (x, y) → ([0, 1), [0, 1))."""
    x = np.asarray(x, dtype=np.int64)
    y = np.asarray(y, dtype=np.int64)
    p = (x * np.int64(374761393) + y * np.int64(668265263) + np.int64(seed)) & np.int64(0xFFFFFFFF)
    p = (p ^ (p >> np.int64(13))) * np.int64(1274126177) & np.int64(0xFFFFFFFF)
    p = p ^ (p >> np.int64(16))
    a = (p & np.int64(0xFFFFFFFF)).astype(np.float32) / np.float32(0xFFFFFFFF)
    p2 = (p * np.int64(2147483647) + np.int64(1013904223)) & np.int64(0xFFFFFFFF)
    p2 = (p2 ^ (p2 >> np.int64(16))) & np.int64(0xFFFFFFFF)
    b = p2.astype(np.float32) / np.float32(0xFFFFFFFF)
    return a, b


def _hash21(x: np.ndarray, y: np.ndarray, seed: int) -> np.ndarray:
    x = np.asarray(x, dtype=np.int64)
    y = np.asarray(y, dtype=np.int64)
    p = (x * np.int64(374761393) + y * np.int64(668265263) + np.int64(seed)) & np.int64(0xFFFFFFFF)
    p = (p ^ (p >> np.int64(13))) * np.int64(1274126177) & np.int64(0xFFFFFFFF)
    p = p ^ (p >> np.int64(16))
    return (p & np.int64(0xFFFFFFFF)).astype(np.float32) / np.float32(0xFFFFFFFF)


def _value_noise_2d(x: np.ndarray, y: np.ndarray, seed: int) -> np.ndarray:
    """Bilinearly smoothed value noise from a deterministic hash."""
    xi = np.floor(x).astype(np.int64)
    yi = np.floor(y).astype(np.int64)
    xf = (x - xi).astype(np.float32)
    yf = (y - yi).astype(np.float32)
    u = xf * xf * (3.0 - 2.0 * xf)
    v = yf * yf * (3.0 - 2.0 * yf)
    n00 = _hash21(xi, yi + seed, 0)
    n10 = _hash21(xi + 1, yi + seed, 0)
    n01 = _hash21(xi, yi + 1 + seed, 0)
    n11 = _hash21(xi + 1, yi + 1 + seed, 0)
    nx0 = n00 * (1.0 - u) + n10 * u
    nx1 = n01 * (1.0 - u) + n11 * u
    return nx0 * (1.0 - v) + nx1 * v


def _fbm(x: np.ndarray, y: np.ndarray, octaves: int, seed: int, lac: float = 2.0, gain: float = 0.5) -> np.ndarray:
    total = np.zeros_like(x, dtype=np.float32)
    amp = np.float32(1.0)
    freq = np.float32(1.0)
    norm = np.float32(0.0)
    for k in range(octaves):
        total = total + amp * _value_noise_2d(x * freq, y * freq, seed + k * 17)
        norm = norm + amp
        amp = amp * np.float32(gain)
        freq = freq * np.float32(lac)
    return total / max(norm, 1e-6)

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/shader_legends_3/BigWingsClouds/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from shader_legends_3

Sample of Animated FBM Nebula with Chromatic Aberration

Animated FBM Nebula with Chromatic Aberration

shader_legends_3 · AshleyGAnimNebula

A multi-coloured, slowly rotating cosmic gas cloud built from 5 layers of FBM noise at different scales, each layer rotated by a different angle that varies with time.

View →
Sample of Atmospheric Perspective Landscape

Atmospheric Perspective Landscape

shader_legends_3 · HubertyAtmospheric

A painterly 2D landscape built from depth-graded FBM bands: a soft sky gradient with a sun disc and cloud streaks, a low-amp haze band in the upper-middle, rolling green midground hills, and a sharp foreground silhouette of trees and grass.

View →
Sample of Bokeh Blur with Light Leaks

Bokeh Blur with Light Leaks

shader_legends_3 · TaterBokeh

A 2D bokeh effect built by stamping 50-200 soft Gaussian discs onto a near-black backdrop, each at a hash-determined centre, radius, and warm-to-cool colour.

View →
Sample of Hash-driven Procedural City Skyline

Hash-driven Procedural City Skyline

shader_legends_3 · DaveHoskinsHashCity

A 2D orthographic night-time cityscape whose per-column building heights come from 1D FBM noise and whose lit windows are a per-cell hash threshold.

View →
Sample of Recursive Spherical Displacement Wireframe

Recursive Spherical Displacement Wireframe

shader_legends_3 · IQDisplacementSphere

A wireframe sphere whose surface is recursively displaced by spherical harmonics of the form amp * sin(N * theta) * cos(M * phi), rendered as overlapping latitude and meridian polylines plus random surface dots.

View →

See all shader_legends_3 artworks →