--- name: postfx-bloom description: Bloom and glow effects using Three.js UnrealBloomPass with React Three Fiber. Use when implementing glow, bloom, luminance-based effects, selective bloom on specific meshes, or neon/ethereal lighting. Essential for cyberpunk aesthetics, energy effects, magic spells, and UI glow. --- # Post-Processing Bloom Bloom effects using UnrealBloomPass for luminance-based glow and selective object bloom. ## Quick Start ```bash npm install three @react-three/fiber @react-three/postprocessing ``` ```tsx import { Canvas } from '@react-three/fiber'; import { EffectComposer, Bloom } from '@react-three/postprocessing'; function Scene() { return ( ); } ``` ## Core Concepts ### How Bloom Works 1. **Threshold** — Pixels brighter than threshold are extracted 2. **Blur** — Extracted pixels are blurred in multiple passes 3. **Composite** — Blurred result is added back to original image ### Key Parameters | Parameter | Range | Description | |-----------|-------|-------------| | `luminanceThreshold` | 0-1 | Brightness cutoff for bloom (lower = more glow) | | `luminanceSmoothing` | 0-1 | Softness of threshold transition | | `intensity` | 0-10 | Bloom brightness multiplier | | `radius` | 0-1 | Blur spread/size | | `levels` | 1-9 | Blur quality/iterations | ## Patterns ### Cosmic Glow Effect ```tsx import { EffectComposer, Bloom } from '@react-three/postprocessing'; import { KernelSize } from 'postprocessing'; function CosmicBloom() { return ( ); } ``` ### Neon Cyberpunk Bloom ```tsx // High-contrast neon with sharp falloff function NeonBloom() { return ( ); } // Emissive material for neon objects function NeonTube({ color = '#FF00FF' }) { return ( ); } ``` ### Selective Bloom with Layers ```tsx import { useRef } from 'react'; import { useThree } from '@react-three/fiber'; import { EffectComposer, SelectiveBloom } from '@react-three/postprocessing'; function SelectiveGlow() { const glowRef = useRef(); return ( <> {/* Non-blooming object */} {/* Blooming object */} ); } ``` ### Multi-Selection Bloom ```tsx import { Selection, Select, EffectComposer } from '@react-three/postprocessing'; import { SelectiveBloom } from '@react-three/postprocessing'; function MultiSelectBloom() { return ( {/* Non-blooming */} {/* Blooming objects wrapped in Select */} ); } ``` ### Animated Bloom Intensity ```tsx import { useRef } from 'react'; import { useFrame } from '@react-three/fiber'; import { EffectComposer, Bloom } from '@react-three/postprocessing'; function PulsingBloom() { const bloomRef = useRef(); useFrame(({ clock }) => { if (bloomRef.current) { const pulse = Math.sin(clock.elapsedTime * 2) * 0.5 + 1.5; bloomRef.current.intensity = pulse; } }); return ( ); } ``` ### Audio-Reactive Bloom ```tsx function AudioReactiveBloom({ audioData }) { const bloomRef = useRef(); useFrame(() => { if (bloomRef.current && audioData) { // Map bass frequency (0-255) to bloom intensity (1-4) const bassLevel = audioData[0] / 255; bloomRef.current.intensity = 1 + bassLevel * 3; // Map mid frequencies to threshold const midLevel = audioData[4] / 255; bloomRef.current.luminanceThreshold = 0.1 + (1 - midLevel) * 0.3; } }); return ( ); } ``` ## Emissive Materials ### Standard Emissive Setup ```tsx // For bloom to work, objects need emissive materials function GlowingSphere({ color = '#00F5FF', intensity = 2 }) { return ( ); } ``` ### Emissive with Texture ```tsx import { useTexture } from '@react-three/drei'; function EmissiveTextured() { const emissiveMap = useTexture('/glow-pattern.png'); return ( ); } ``` ### Shader Material with Emissive ```tsx import { shaderMaterial } from '@react-three/drei'; import { extend } from '@react-three/fiber'; const GlowMaterial = shaderMaterial( { uTime: 0, uColor: [0, 0.96, 1], uIntensity: 2.0 }, // Vertex shader ` varying vec2 vUv; void main() { vUv = uv; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, // Fragment shader - outputs HDR values for bloom ` uniform float uTime; uniform vec3 uColor; uniform float uIntensity; varying vec2 vUv; void main() { float pulse = sin(uTime * 2.0) * 0.3 + 0.7; vec3 glow = uColor * uIntensity * pulse; gl_FragColor = vec4(glow, 1.0); } ` ); extend({ GlowMaterial }); function PulsingGlowMesh() { const materialRef = useRef(); useFrame(({ clock }) => { materialRef.current.uTime = clock.elapsedTime; }); return ( ); } ``` ## Performance Optimization ### Resolution Scaling ```tsx ``` ### Mobile-Optimized Bloom ```tsx import { useDetectGPU } from '@react-three/drei'; function AdaptiveBloom() { const { tier } = useDetectGPU(); const config = tier < 2 ? { levels: 3, radius: 0.5, intensity: 1.0 } : { levels: 5, radius: 0.8, intensity: 1.5 }; return ( ); } ``` ## Temporal Collapse Theme Bloom configuration for the New Year countdown cosmic aesthetic: ```tsx // Cosmic void with cyan/magenta glow function TemporalCollapseBloom() { return ( ); } // Color palette for emissive materials const TEMPORAL_COLORS = { cyan: '#00F5FF', magenta: '#FF00FF', gold: '#FFD700', void: '#050508' }; // Time digit with glow function GlowingDigit({ digit, color = TEMPORAL_COLORS.cyan }) { return ( {digit} ); } ``` ## Troubleshooting | Issue | Solution | |-------|----------| | No bloom visible | Ensure `emissiveIntensity > 1` and `toneMapped={false}` | | Bloom too subtle | Lower `luminanceThreshold`, increase `intensity` | | Performance issues | Reduce `levels`, enable `mipmapBlur`, disable multisampling | | Selective bloom not working | Verify `ref` is passed and object has emissive material | | Bloom bleeding everywhere | Raise `luminanceThreshold` to isolate bright areas | ## Reference - See `postfx-composer` for EffectComposer setup patterns - See `postfx-effects` for combining bloom with other effects - See `shaders-glsl` for custom emissive shader techniques