Post-Processing Bloom
Bloom effects using UnrealBloomPass for luminance-based glow and selective object bloom.
Quick Start npm install three @react-three/fiber @react-three/postprocessing
import { Canvas } from '@react-three/fiber'; import { EffectComposer, Bloom } from '@react-three/postprocessing';
function Scene() { return (
<EffectComposer>
<Bloom
luminanceThreshold={0.2}
luminanceSmoothing={0.9}
intensity={1.5}
/>
</EffectComposer>
</Canvas>
); }
Core Concepts How Bloom Works Threshold — Pixels brighter than threshold are extracted Blur — Extracted pixels are blurred in multiple passes 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 import { EffectComposer, Bloom } from '@react-three/postprocessing'; import { KernelSize } from 'postprocessing';
function CosmicBloom() {
return (
Neon Cyberpunk Bloom
// High-contrast neon with sharp falloff
function NeonBloom() {
return (
// Emissive material for neon objects
function NeonTube({ color = '#FF00FF' }) {
return (
Selective Bloom with Layers 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 */}
<mesh ref={glowRef} position={[2, 0, 0]}>
<sphereGeometry args={[0.5, 32, 32]} />
<meshStandardMaterial
emissive="#00F5FF"
emissiveIntensity={3}
/>
</mesh>
<EffectComposer>
<SelectiveBloom
selection={glowRef}
luminanceThreshold={0.1}
intensity={2}
mipmapBlur
/>
</EffectComposer>
</>
); }
Multi-Selection Bloom import { Selection, Select, EffectComposer } from '@react-three/postprocessing'; import { SelectiveBloom } from '@react-three/postprocessing';
function MultiSelectBloom() {
return (
{/* Blooming objects wrapped in Select */}
<Select enabled>
<mesh position={[0, 0, 0]}>
<sphereGeometry args={[0.5]} />
<meshStandardMaterial emissive="#00F5FF" emissiveIntensity={2} />
</mesh>
</Select>
<Select enabled>
<mesh position={[2, 0, 0]}>
<octahedronGeometry args={[0.5]} />
<meshStandardMaterial emissive="#FF00FF" emissiveIntensity={2} />
</mesh>
</Select>
<EffectComposer>
<SelectiveBloom
luminanceThreshold={0.1}
intensity={1.5}
mipmapBlur
/>
</EffectComposer>
</Selection>
); }
Animated Bloom Intensity 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 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
// For bloom to work, objects need emissive materials
function GlowingSphere({ color = '#00F5FF', intensity = 2 }) {
return (
Emissive with Texture import { useTexture } from '@react-three/drei';
function EmissiveTextured() { const emissiveMap = useTexture('/glow-pattern.png');
return (
Shader Material with Emissive 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 <EffectComposer multisampling={0} // Disable MSAA for performance
Mobile-Optimized Bloom 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 (
<EffectComposer multisampling={tier < 2 ? 0 : 4}>
Temporal Collapse Theme
Bloom configuration for the New Year countdown cosmic aesthetic:
// 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 (
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