How to Create a Realistic Rain Effect in the Browser with Three.js and Shaders

This article explores various techniques—from CSS animation to WebGL shaders—for rendering rain in a browser, analyzes the underlying algorithms, provides GLSL and Three.js code examples, and discusses performance optimizations and extensions such as snow effects.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
How to Create a Realistic Rain Effect in the Browser with Three.js and Shaders

My Browser Is Raining

Origin

While checking the weather on a rainy day, I discovered a striking rain‑drop effect on a web page and wondered how to implement it if a project manager demanded it.

The effect simulates raindrops sliding across the screen, covering the whole browser, which sparked curiosity about possible implementation approaches.

CSS Animation : Use CSS3 animations and opacity changes to mimic falling drops; simple but limited in flexibility.

JavaScript DOM : Dynamically create drop elements and control their motion with JS; suitable for simple scenes but may impact performance.

Canvas : Draw drops frame‑by‑frame on a canvas, allowing complex physics like collisions and splashes; good performance and visual quality.

WebGL / Shader : Render drops directly on the GPU with WebGL or GLSL shaders for high‑fidelity visuals; steep learning curve.

Although I have not yet built the effect myself, I analyzed the technical challenges and possible solutions.

Exploration and Learning

I researched each method, noting pros and cons, and decided to dive deeper into the shader‑based approach.

Algorithm Analysis

Rain Drop Generation : Randomly generate positions and sizes using a pseudo‑random function.

Rain Drop Motion : Use a time variable to control falling speed and loop to regenerate drops.

Background Texture : Add a gradient background for realism.

Key GLSL code:

// Generate pseudo‑random numbers
vec3 N13(float p) {
    vec3 p3 = fract(vec3(p) * vec3(.1031, .11369, .13787));
    p3 += dot(p3, p3.yzx + 19.19);
    return fract(vec3((p3.x + p3.y) * p3.z,
                     (p3.x + p3.z) * p3.y,
                     (p3.y + p3.z) * p3.x));
}

// Rain drop layer
vec2 DropLayer2(vec2 uv, float t) {
    uv.y += t * 0.75; // time‑driven fall
    vec2 grid = vec2(6., 1.) * 2.; // grid division
    vec2 id = floor(uv * grid); // current cell id
    vec3 n = N13(id.x * 35.2 + id.y * 2376.1); // random parameters
    vec2 st = fract(uv * grid) - vec2(.5, 0); // local coordinates
    float d = length((st - vec2(n.x - .5, n.y - .5)) * vec2(1., 1.5)); // distance
    return vec2(smoothstep(.4, .0, d), 0.0); // drop shape
}

Implementation with Three.js

Using Three.js ShaderMaterial to embed the GLSL code:

const material = new THREE.ShaderMaterial({
    uniforms: {
        iResolution: { value: new THREE.Vector3() }, // screen resolution
        iTime: { value: 0 }, // animation time
        iChannel0: { value: bgTexture } // background texture
    },
    vertexShader: `
        varying vec2 vUv;
        void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `,
    fragmentShader: `
        precision highp float;
        varying vec2 vUv;
        uniform float iTime;
        uniform vec3 iResolution;
        void main() {
            vec2 uv = vUv;
            float t = iTime;
            vec2 drops = DropLayer2(uv, t);
            gl_FragColor = vec4(vec3(drops.x), 1.0);
        }
    `
});

Performance and Practice

GPU Acceleration : Shaders run on the GPU, handling thousands of pixels efficiently.

Animation Loop : Use requestAnimationFrame and performance.now() for high‑frame‑rate animation.

UI Interaction : Sliders can adjust rain intensity, speed, and other parameters in real time.

Related Knowledge

GLSL : A C‑like language for writing graphics shaders.

WebGL : Browser 3D rendering API based on OpenGL ES.

Three.js : A JavaScript library that simplifies WebGL development.

Easter Egg: How to Make It Snow

Slow down the drop speed, change the shape to round, and set the color to white; the same algorithm produces a snow effect.

Conclusion

The "browser rain" experiment demonstrates front‑end graphics techniques, AI‑assisted code analysis, and how to meet demanding visual requirements using WebGL and Three.js, while also offering extensions like snow and performance tips.

Technology’s joy lies not only in implementation but also in exploration and sharing.
frontendCanvasThree.jsWebGLShaderrain effect
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.