Atmospheric Effects and Fog Systems
The mist system uses custom shader materials with per-particle attributes to create an atmospheric fog effect reminiscent of Chinese landscape paintings. Each mist particle has a random size, uses GPU-based animation for optimal performance, clusters organically through random positioning, and animates with gentle floating motion using sine waves.
The visualization above demonstrates the fog particle system. Adjust particle count, animation speed, and particle size to see how these parameters affect the atmospheric effect. Click and drag to rotate the camera, or scroll to zoom.
Technical Implementation
The fog system uses GPU-based animation for optimal performance, moving all calculations to the vertex shader:
// Create mist particles
const mistGeometry = new THREE.BufferGeometry();
const particleCount = 200;
const positions = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);
for (let i = 0; i < particleCount; i++) {
const i3 = i * 3;
positions[i3] = (Math.random() - 0.5) * 20;
positions[i3 + 1] = Math.random() * 5;
positions[i3 + 2] = (Math.random() - 0.5) * 20;
sizes[i] = 0.5 + Math.random() * 1.5;
}
mistGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
mistGeometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));
// GPU-based shader material
const mistMaterial = new THREE.ShaderMaterial({
uniforms: { time: { value: 0 } },
vertexShader: `
attribute float size;
uniform float time;
void main() {
vec3 pos = position;
// Animate on GPU - no CPU updates needed!
pos.y += sin(time + position.x * 0.1 + position.z * 0.1) * 0.1;
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
gl_PointSize = size * (300.0 / -mvPosition.z);
gl_Position = projectionMatrix * mvPosition;
}
`,
fragmentShader: `
void main() {
float dist = length(gl_PointCoord - vec2(0.5));
float alpha = 1.0 - smoothstep(0.0, 0.5, dist);
gl_FragColor = vec4(1.0, 1.0, 1.0, alpha * 0.3);
}
`,
transparent: true,
blending: THREE.AdditiveBlending,
depthWrite: false,
});
GPU-Based Animation
All animation happens in the vertex shader, which means:
-
No CPU overhead: No JavaScript updates needed each frame
-
Highly efficient: GPU processes all particles in parallel
-
Smooth performance: Can handle hundreds of particles without frame drops
The animation uses sine waves with different phases for each particle, creating organic, floating motion:
pos.y += sin(time + position.x * 0.1 + position.z * 0.1) * 0.1;
Each particle moves based on its position and the current time, creating varied motion patterns.
Visual Aesthetic
The fog system creates an atmospheric effect that:
-
Clusters organically through random positioning
-
Floats gently with sine wave animation
-
Adds depth to the scene with atmospheric perspective
-
Matches the aesthetic of Chinese landscape paintings
The particles use additive blending to create a soft, glowing effect that enhances the minimalist, stylized look of the background.
Performance Optimization
The fog system is optimized for performance:
-
GPU-based animation (no CPU updates)
-
Efficient point sprite rendering
-
Configurable particle count (typically 200-400 particles)
-
IntersectionObserver pauses rendering when not visible
References
-
Three.js Points - Point sprite rendering
-
WebGL Shaders - Shader programming basics
-
Particle Systems - General particle system concepts
Related Articles
-
The 3d background - Overview of the animated background system
-
3d Background - Cell Shading - Rendering techniques used in the scene
-
Performance Optimization - Performance considerations for the background
Sub-Topics
Explore specific atmospheric effects:
- 3d Background - Atmospheric Effects - Fog Visualization - Detailed fog implementation
- 3d Background - Atmospheric Effects - Rain Visualization - Rain particle systems
- 3d Background - Atmospheric Effects - Snow Visualization - Snow effects and accumulation