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.
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.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
