ShaderToMP4

HomeAccueil / ExamplesExemples

MetaballsBoules fusionnantes

Smooth union (smooth minimum) of four moving spheres: they melt together when they get close.Union lisse (smooth minimum) de quatre sphères mobiles : elles se fondent quand elles se rapprochent.

Metaballs / Boules fusionnantes

CategoryCatégorie: Ray marchingRay marching - metaballs.glsl - 33 lineslignes - File on GitHubFichier sur GitHub

In the program: Examples, choose it, Add to the list. Or copy the code into a file next to the program and drop it on the window.Dans le programme : Exemples, choisissez-le, Ajouter à la liste. Ou copiez le code dans un fichier et glissez-le sur la fenêtre.

CodeCode

metaballs.glsl

// SPDX-License-Identifier: GPL-3.0-or-later
// Copyright (C) 2026 Patrick JAILLET

// fr: Boules fusionnantes — Union lisse (smooth minimum) de quatre sphères mobiles : elles se fondent quand elles se rapprochent.
// en: Metaballs — Smooth union (smooth minimum) of four moving spheres: they melt together when they get close.

float smin(float a, float b, float k) { float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0); return mix(b, a, h) - k * h * (1.0 - h); }
float map(vec3 p) {
    float d = 1e9;
    for (int i = 0; i < 4; i++) {
        float f = float(i);
        vec3 c = 0.9 * vec3(sin(iTime * 0.7 + f * 1.7), sin(iTime * 0.9 + f * 2.3), cos(iTime * 0.6 + f));
        d = smin(d, length(p - c) - 0.55, 0.5);
    }
    return d;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y;
    vec3 ro = vec3(0.0, 0.0, -4.0), rd = normalize(vec3(uv, 1.6));
    float t = 0.0;
    for (int i = 0; i < 80; i++) { float d = map(ro + rd * t); if (d < 0.001 || t > 10.0) break; t += d; }
    vec3 col = mix(vec3(0.02, 0.0, 0.08), vec3(0.15, 0.05, 0.2), uv.y + 0.5);
    if (t < 10.0) {
        vec3 p = ro + rd * t;
        vec2 e = vec2(0.001, 0.0);
        vec3 n = normalize(vec3(map(p + e.xyy) - map(p - e.xyy), map(p + e.yxy) - map(p - e.yxy), map(p + e.yyx) - map(p - e.yyx)));
        col = 0.5 + 0.5 * n;
        col *= 0.3 + 0.7 * max(dot(n, normalize(vec3(0.4, 0.8, -0.5))), 0.0);
        col += pow(max(dot(reflect(rd, n), normalize(vec3(0.4, 0.8, -0.5))), 0.0), 30.0);
    }
    fragColor = vec4(pow(col, vec3(0.4545)), 1.0);
}