r3f-postprocessing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReact Three Fiber Post-Processing
React Three Fiber 后处理
Quick Start
快速开始
tsx
import { Canvas } from '@react-three/fiber'
import { EffectComposer, Bloom, Vignette } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
<ambientLight />
<mesh>
<boxGeometry />
<meshStandardMaterial color="hotpink" emissive="hotpink" emissiveIntensity={2} />
</mesh>
<EffectComposer>
<Bloom luminanceThreshold={0.5} luminanceSmoothing={0.9} intensity={1.5} />
<Vignette offset={0.5} darkness={0.5} />
</EffectComposer>
</Canvas>
)
}tsx
import { Canvas } from '@react-three/fiber'
import { EffectComposer, Bloom, Vignette } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
<ambientLight />
<mesh>
<boxGeometry />
<meshStandardMaterial color="hotpink" emissive="hotpink" emissiveIntensity={2} />
</mesh>
<EffectComposer>
<Bloom luminanceThreshold={0.5} luminanceSmoothing={0.9} intensity={1.5} />
<Vignette offset={0.5} darkness={0.5} />
</EffectComposer>
</Canvas>
)
}Installation
安装
bash
npm install @react-three/postprocessing postprocessingbash
npm install @react-three/postprocessing postprocessingEffectComposer
EffectComposer
The container for all post-processing effects.
tsx
import { EffectComposer } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
{/* Scene content */}
<mesh>...</mesh>
{/* Post-processing - must be inside Canvas, after scene content */}
<EffectComposer
enabled={true} // Toggle all effects
depthBuffer={true} // Enable depth buffer
stencilBuffer={false} // Enable stencil buffer
autoClear={true} // Auto clear before render
multisampling={8} // MSAA samples (0 to disable)
>
{/* Effects go here */}
</EffectComposer>
</Canvas>
)
}所有后处理特效的容器。
tsx
import { EffectComposer } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
{/* 场景内容 */}
<mesh>...</mesh>
{/* 后处理 - 必须放在Canvas内部,场景内容之后 */}
<EffectComposer
enabled={true} // 切换所有特效的启用状态
depthBuffer={true} // 启用深度缓冲区
stencilBuffer={false} // 启用模板缓冲区
autoClear={true} // 渲染前自动清除
multisampling={8} // MSAA采样数(0表示禁用)
>
{/* 特效放在这里 */}
</EffectComposer>
</Canvas>
)
}Common Effects
常用特效
Bloom (Glow)
Bloom(发光效果)
tsx
import { EffectComposer, Bloom } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Bloom
intensity={1.0} // Bloom intensity
luminanceThreshold={0.9} // Brightness threshold
luminanceSmoothing={0.025} // Smoothness of threshold
mipmapBlur={true} // Enable mipmap blur
radius={0.8} // Bloom radius
levels={8} // Mipmap levels
blendFunction={BlendFunction.ADD}
/>
</EffectComposer>
// For objects to glow, use emissive materials
<mesh>
<boxGeometry />
<meshStandardMaterial
color="black"
emissive="#ff00ff"
emissiveIntensity={2}
toneMapped={false} // Important for values > 1
/>
</mesh>tsx
import { EffectComposer, Bloom } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Bloom
intensity={1.0} // 发光强度
luminanceThreshold={0.9} // 亮度阈值
luminanceSmoothing={0.025} // 阈值平滑度
mipmapBlur={true} // 启用mipmap模糊
radius={0.8} // 发光半径
levels={8} // Mipmap层级
blendFunction={BlendFunction.ADD}
/>
</EffectComposer>
// 要让物体发光,使用自发光材质
<mesh>
<boxGeometry />
<meshStandardMaterial
color="black"
emissive="#ff00ff"
emissiveIntensity={2}
toneMapped={false} // 当值大于1时,此项很重要
/>
</mesh>Selective Bloom
选择性发光
tsx
import { EffectComposer, Bloom, Selection, Select } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
<Selection>
<EffectComposer>
<Bloom
luminanceThreshold={0}
intensity={2}
mipmapBlur
/>
</EffectComposer>
{/* This mesh will bloom */}
<Select enabled>
<mesh>
<sphereGeometry />
<meshStandardMaterial emissive="red" emissiveIntensity={2} toneMapped={false} />
</mesh>
</Select>
{/* This mesh will NOT bloom */}
<mesh position={[2, 0, 0]}>
<boxGeometry />
<meshStandardMaterial color="blue" />
</mesh>
</Selection>
</Canvas>
)
}tsx
import { EffectComposer, Bloom, Selection, Select } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
<Selection>
<EffectComposer>
<Bloom
luminanceThreshold={0}
intensity={2}
mipmapBlur
/>
</EffectComposer>
{/* 这个网格会发光 */}
<Select enabled>
<mesh>
<sphereGeometry />
<meshStandardMaterial emissive="red" emissiveIntensity={2} toneMapped={false} />
</mesh>
</Select>
{/* 这个网格不会发光 */}
<mesh position={[2, 0, 0]}>
<boxGeometry />
<meshStandardMaterial color="blue" />
</mesh>
</Selection>
</Canvas>
)
}Depth of Field
景深(Depth of Field)
tsx
import { EffectComposer, DepthOfField } from '@react-three/postprocessing'
<EffectComposer>
<DepthOfField
focusDistance={0} // Focus distance (0 = auto)
focalLength={0.02} // Camera focal length
bokehScale={2} // Bokeh size
height={480} // Resolution height
/>
</EffectComposer>
// With target object
import { useRef } from 'react'
function Scene() {
const targetRef = useRef()
return (
<>
<mesh ref={targetRef} position={[0, 0, -5]}>
<boxGeometry />
<meshStandardMaterial color="red" />
</mesh>
<EffectComposer>
<DepthOfField
target={targetRef}
focalLength={0.02}
bokehScale={2}
/>
</EffectComposer>
</>
)
}tsx
import { EffectComposer, DepthOfField } from '@react-three/postprocessing'
<EffectComposer>
<DepthOfField
focusDistance={0} // 对焦距离(0表示自动对焦)
focalLength={0.02} // 相机焦距
bokehScale={2} // 散景大小
height={480} // 分辨率高度
/>
</EffectComposer>
// 绑定目标物体
import { useRef } from 'react'
function Scene() {
const targetRef = useRef()
return (
<>
<mesh ref={targetRef} position={[0, 0, -5]}>
<boxGeometry />
<meshStandardMaterial color="red" />
</mesh>
<EffectComposer>
<DepthOfField
target={targetRef}
focalLength={0.02}
bokehScale={2}
/>
</EffectComposer>
</>
)
}Vignette
暗角(Vignette)
tsx
import { EffectComposer, Vignette } from '@react-three/postprocessing'
<EffectComposer>
<Vignette
offset={0.5} // Vignette size
darkness={0.5} // Vignette intensity
eskil={false} // Use Eskil's vignette technique
/>
</EffectComposer>tsx
import { EffectComposer, Vignette } from '@react-three/postprocessing'
<EffectComposer>
<Vignette
offset={0.5} // 暗角大小
darkness={0.5} // 暗角强度
eskil={false} // 使用Eskil的暗角技术
/>
</EffectComposer>Noise
噪点效果
tsx
import { EffectComposer, Noise } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Noise
premultiply // Multiply noise with input
blendFunction={BlendFunction.ADD}
opacity={0.5}
/>
</EffectComposer>tsx
import { EffectComposer, Noise } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Noise
premultiply // 将噪点与输入内容相乘
blendFunction={BlendFunction.ADD}
opacity={0.5}
/>
</EffectComposer>Chromatic Aberration
色差(Chromatic Aberration)
tsx
import { EffectComposer, ChromaticAberration } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<ChromaticAberration
offset={[0.002, 0.002]} // Color offset
radialModulation={true} // Apply radially
modulationOffset={0.5}
blendFunction={BlendFunction.NORMAL}
/>
</EffectComposer>tsx
import { EffectComposer, ChromaticAberration } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<ChromaticAberration
offset={[0.002, 0.002]} // 颜色偏移量
radialModulation={true} // 应用径向调制
modulationOffset={0.5}
blendFunction={BlendFunction.NORMAL}
/>
</EffectComposer>SSAO (Screen Space Ambient Occlusion)
屏幕空间环境光遮蔽(SSAO)
tsx
import { EffectComposer, SSAO } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<SSAO
blendFunction={BlendFunction.MULTIPLY}
samples={30} // Amount of samples
radius={5} // Occlusion radius
intensity={30} // Occlusion intensity
luminanceInfluence={0.6}
color="black"
worldDistanceThreshold={100}
worldDistanceFalloff={5}
worldProximityThreshold={0.01}
worldProximityFalloff={0.01}
/>
</EffectComposer>tsx
import { EffectComposer, SSAO } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<SSAO
blendFunction={BlendFunction.MULTIPLY}
samples={30} // 采样数量
radius={5} // 遮蔽半径
intensity={30} // 遮蔽强度
luminanceInfluence={0.6}
color="black"
worldDistanceThreshold={100}
worldDistanceFalloff={5}
worldProximityThreshold={0.01}
worldProximityFalloff={0.01}
/>
</EffectComposer>Outline
轮廓线(Outline)
tsx
import { EffectComposer, Outline, Selection, Select } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
<Selection>
<EffectComposer autoClear={false}>
<Outline
visibleEdgeColor={0xffffff} // Visible edge color
hiddenEdgeColor={0x22090a} // Hidden edge color
edgeStrength={2.5} // Edge strength
pulseSpeed={0} // Pulse animation speed
blur // Enable blur
xRay // Show behind objects
/>
</EffectComposer>
{/* Outlined object */}
<Select enabled>
<mesh>
<boxGeometry />
<meshStandardMaterial color="orange" />
</mesh>
</Select>
{/* Non-outlined object */}
<mesh position={[2, 0, 0]}>
<sphereGeometry />
<meshStandardMaterial color="blue" />
</mesh>
</Selection>
</Canvas>
)
}tsx
import { EffectComposer, Outline, Selection, Select } from '@react-three/postprocessing'
function Scene() {
return (
<Canvas>
<Selection>
<EffectComposer autoClear={false}>
<Outline
visibleEdgeColor={0xffffff} // 可见边缘颜色
hiddenEdgeColor={0x22090a} // 隐藏边缘颜色
edgeStrength={2.5} // 边缘强度
pulseSpeed={0} // 脉冲动画速度
blur // 启用模糊
xRay // 显示物体后方的轮廓
/>
</EffectComposer>
{/* 带轮廓线的物体 */}
<Select enabled>
<mesh>
<boxGeometry />
<meshStandardMaterial color="orange" />
</mesh>
</Select>
{/* 不带轮廓线的物体 */}
<mesh position={[2, 0, 0]}>
<sphereGeometry />
<meshStandardMaterial color="blue" />
</mesh>
</Selection>
</Canvas>
)
}Color Grading
色彩分级
tsx
import { EffectComposer, BrightnessContrast, HueSaturation } from '@react-three/postprocessing'
<EffectComposer>
<BrightnessContrast
brightness={0} // -1 to 1
contrast={0} // -1 to 1
/>
<HueSaturation
hue={0} // Hue rotation in radians
saturation={0} // -1 to 1
/>
</EffectComposer>tsx
import { EffectComposer, BrightnessContrast, HueSaturation } from '@react-three/postprocessing'
<EffectComposer>
<BrightnessContrast
brightness={0} // 取值范围-1到1
contrast={0} // 取值范围-1到1
/>
<HueSaturation
hue={0} // 色相旋转角度(弧度)
saturation={0} // 取值范围-1到1
/>
</EffectComposer>Tone Mapping
色调映射
tsx
import { EffectComposer, ToneMapping } from '@react-three/postprocessing'
import { ToneMappingMode } from 'postprocessing'
<EffectComposer>
<ToneMapping
mode={ToneMappingMode.ACES_FILMIC}
// Modes: LINEAR, REINHARD, REINHARD2, OPTIMIZED_CINEON, CINEON, ACES_FILMIC, AGX, NEUTRAL
resolution={256}
whitePoint={4.0}
middleGrey={0.6}
minLuminance={0.01}
averageLuminance={1.0}
adaptationRate={1.0}
/>
</EffectComposer>tsx
import { EffectComposer, ToneMapping } from '@react-three/postprocessing'
import { ToneMappingMode } from 'postprocessing'
<EffectComposer>
<ToneMapping
mode={ToneMappingMode.ACES_FILMIC}
// 可选模式:LINEAR, REINHARD, REINHARD2, OPTIMIZED_CINEON, CINEON, ACES_FILMIC, AGX, NEUTRAL
resolution={256}
whitePoint={4.0}
middleGrey={0.6}
minLuminance={0.01}
averageLuminance={1.0}
adaptationRate={1.0}
/>
</EffectComposer>Glitch
故障效果(Glitch)
tsx
import { EffectComposer, Glitch } from '@react-three/postprocessing'
import { GlitchMode } from 'postprocessing'
<EffectComposer>
<Glitch
delay={[1.5, 3.5]} // Min/max delay between glitches
duration={[0.6, 1.0]} // Min/max duration
strength={[0.3, 1.0]} // Min/max strength
mode={GlitchMode.SPORADIC} // DISABLED, SPORADIC, CONSTANT_MILD, CONSTANT_WILD
active // Enable/disable
ratio={0.85} // Glitch ratio (0 = none, 1 = always)
/>
</EffectComposer>tsx
import { EffectComposer, Glitch } from '@react-three/postprocessing'
import { GlitchMode } from 'postprocessing'
<EffectComposer>
<Glitch
delay={[1.5, 3.5]} // 故障间隔的最小/最大值
duration={[0.6, 1.0]} // 故障持续时间的最小/最大值
strength={[0.3, 1.0]} // 故障强度的最小/最大值
mode={GlitchMode.SPORADIC} // 可选模式:DISABLED, SPORADIC, CONSTANT_MILD, CONSTANT_WILD
active // 启用/禁用故障效果
ratio={0.85} // 故障出现比例(0表示无,1表示持续出现)
/>
</EffectComposer>Pixelation
像素化效果
tsx
import { EffectComposer, Pixelation } from '@react-three/postprocessing'
<EffectComposer>
<Pixelation
granularity={5} // Pixel size
/>
</EffectComposer>tsx
import { EffectComposer, Pixelation } from '@react-three/postprocessing'
<EffectComposer>
<Pixelation
granularity={5} // 像素大小
/>
</EffectComposer>Scanline
扫描线效果
tsx
import { EffectComposer, Scanline } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Scanline
blendFunction={BlendFunction.OVERLAY}
density={1.25} // Line density
opacity={0.5} // Effect opacity
/>
</EffectComposer>tsx
import { EffectComposer, Scanline } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Scanline
blendFunction={BlendFunction.OVERLAY}
density={1.25} // 扫描线密度
opacity={0.5} // 效果透明度
/>
</EffectComposer>Grid
网格效果
tsx
import { EffectComposer, Grid } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Grid
blendFunction={BlendFunction.OVERLAY}
scale={1.0} // Grid scale
lineWidth={0.0} // Line width
/>
</EffectComposer>tsx
import { EffectComposer, Grid } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<Grid
blendFunction={BlendFunction.OVERLAY}
scale={1.0} // 网格缩放比例
lineWidth={0.0} // 线条宽度
/>
</EffectComposer>DotScreen
网点效果
tsx
import { EffectComposer, DotScreen } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<DotScreen
blendFunction={BlendFunction.NORMAL}
angle={Math.PI * 0.5} // Pattern angle
scale={1.0} // Pattern scale
/>
</EffectComposer>tsx
import { EffectComposer, DotScreen } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
<EffectComposer>
<DotScreen
blendFunction={BlendFunction.NORMAL}
angle={Math.PI * 0.5} // 图案角度
scale={1.0} // 图案缩放比例
/>
</EffectComposer>SMAA (Anti-Aliasing)
SMAA(抗锯齿)
tsx
import { EffectComposer, SMAA } from '@react-three/postprocessing'
<EffectComposer multisampling={0}> {/* Disable MSAA when using SMAA */}
<SMAA />
</EffectComposer>tsx
import { EffectComposer, SMAA } from '@react-three/postprocessing'
<EffectComposer multisampling={0}> {/* 使用SMAA时禁用MSAA */}
<SMAA />
</EffectComposer>FXAA (Anti-Aliasing)
FXAA(抗锯齿)
tsx
import { EffectComposer, FXAA } from '@react-three/postprocessing'
<EffectComposer multisampling={0}>
<FXAA />
</EffectComposer>tsx
import { EffectComposer, FXAA } from '@react-three/postprocessing'
<EffectComposer multisampling={0}>
<FXAA />
</EffectComposer>Combining Multiple Effects
组合多种特效
tsx
import { EffectComposer, Bloom, Vignette, ChromaticAberration, Noise, SMAA } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
function PostProcessing() {
return (
<EffectComposer multisampling={0}>
{/* Glow effect */}
<Bloom
intensity={1.5}
luminanceThreshold={0.9}
luminanceSmoothing={0.025}
mipmapBlur
/>
{/* Color aberration */}
<ChromaticAberration
offset={[0.001, 0.001]}
radialModulation
modulationOffset={0.5}
/>
{/* Film grain */}
<Noise
premultiply
blendFunction={BlendFunction.ADD}
opacity={0.2}
/>
{/* Vignette */}
<Vignette
offset={0.3}
darkness={0.5}
/>
{/* Anti-aliasing (should be last) */}
<SMAA />
</EffectComposer>
)
}tsx
import { EffectComposer, Bloom, Vignette, ChromaticAberration, Noise, SMAA } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing'
function PostProcessing() {
return (
<EffectComposer multisampling={0}>
{/* 发光效果 */}
<Bloom
intensity={1.5}
luminanceThreshold={0.9}
luminanceSmoothing={0.025}
mipmapBlur
/>
{/* 色差效果 */}
<ChromaticAberration
offset={[0.001, 0.001]}
radialModulation
modulationOffset={0.5}
/>
{/* 胶片颗粒效果 */}
<Noise
premultiply
blendFunction={BlendFunction.ADD}
opacity={0.2}
/>
{/* 暗角效果 */}
<Vignette
offset={0.3}
darkness={0.5}
/>
{/* 抗锯齿(应放在最后) */}
<SMAA />
</EffectComposer>
)
}Custom Effects
自定义特效
Using postprocessing Effect Class
使用postprocessing的Effect类
tsx
import { forwardRef, useMemo } from 'react'
import { Effect, BlendFunction } from 'postprocessing'
import { Uniform } from 'three'
// Fragment shader
const fragmentShader = `
uniform float time;
uniform float intensity;
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
vec2 distortedUv = uv;
distortedUv.x += sin(uv.y * 10.0 + time) * 0.01 * intensity;
vec4 color = texture2D(inputBuffer, distortedUv);
outputColor = color;
}
`
// Effect class
class WaveDistortionEffect extends Effect {
constructor({ intensity = 1.0, blendFunction = BlendFunction.NORMAL } = {}) {
super('WaveDistortionEffect', fragmentShader, {
blendFunction,
uniforms: new Map([
['time', new Uniform(0)],
['intensity', new Uniform(intensity)],
]),
})
}
update(renderer, inputBuffer, deltaTime) {
this.uniforms.get('time').value += deltaTime
}
}
// React component wrapper
export const WaveDistortion = forwardRef(({ intensity = 1.0, blendFunction }, ref) => {
const effect = useMemo(() => new WaveDistortionEffect({ intensity, blendFunction }), [intensity, blendFunction])
return <primitive ref={ref} object={effect} dispose={null} />
})
// Usage
<EffectComposer>
<WaveDistortion intensity={0.5} />
</EffectComposer>tsx
import { forwardRef, useMemo } from 'react'
import { Effect, BlendFunction } from 'postprocessing'
import { Uniform } from 'three'
// 片元着色器
const fragmentShader = `
uniform float time;
uniform float intensity;
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
vec2 distortedUv = uv;
distortedUv.x += sin(uv.y * 10.0 + time) * 0.01 * intensity;
vec4 color = texture2D(inputBuffer, distortedUv);
outputColor = color;
}
`
// 特效类
class WaveDistortionEffect extends Effect {
constructor({ intensity = 1.0, blendFunction = BlendFunction.NORMAL } = {}) {
super('WaveDistortionEffect', fragmentShader, {
blendFunction,
uniforms: new Map([
['time', new Uniform(0)],
['intensity', new Uniform(intensity)],
]),
})
}
update(renderer, inputBuffer, deltaTime) {
this.uniforms.get('time').value += deltaTime
}
}
// React组件包装器
export const WaveDistortion = forwardRef(({ intensity = 1.0, blendFunction }, ref) => {
const effect = useMemo(() => new WaveDistortionEffect({ intensity, blendFunction }), [intensity, blendFunction])
return <primitive ref={ref} object={effect} dispose={null} />
})
// 使用示例
<EffectComposer>
<WaveDistortion intensity={0.5} />
</EffectComposer>Shader with wrapEffect
使用wrapEffect创建着色器特效
tsx
import { wrapEffect } from '@react-three/postprocessing'
import { Effect, BlendFunction } from 'postprocessing'
import { Uniform } from 'three'
class InvertEffect extends Effect {
constructor({ blendFunction = BlendFunction.NORMAL } = {}) {
super('InvertEffect', `
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
outputColor = vec4(1.0 - inputColor.rgb, inputColor.a);
}
`, {
blendFunction,
})
}
}
export const Invert = wrapEffect(InvertEffect)
// Usage
<EffectComposer>
<Invert />
</EffectComposer>tsx
import { wrapEffect } from '@react-three/postprocessing'
import { Effect, BlendFunction } from 'postprocessing'
class InvertEffect extends Effect {
constructor({ blendFunction = BlendFunction.NORMAL } = {}) {
super('InvertEffect', `
void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
outputColor = vec4(1.0 - inputColor.rgb, inputColor.a);
}
`, {
blendFunction,
})
}
}
export const Invert = wrapEffect(InvertEffect)
// 使用示例
<EffectComposer>
<Invert />
</EffectComposer>Conditional Effects
条件启用特效
tsx
import { useState } from 'react'
import { EffectComposer, Bloom, Vignette, Glitch } from '@react-three/postprocessing'
function ConditionalPostProcessing() {
const [effects, setEffects] = useState({
bloom: true,
vignette: true,
glitch: false,
})
return (
<>
<EffectComposer>
{effects.bloom && (
<Bloom intensity={1.5} luminanceThreshold={0.9} />
)}
{effects.vignette && (
<Vignette offset={0.5} darkness={0.5} />
)}
{effects.glitch && (
<Glitch delay={[1, 3]} duration={[0.5, 1]} strength={[0.3, 1]} />
)}
</EffectComposer>
{/* UI to toggle effects */}
<div className="controls">
<button onClick={() => setEffects(e => ({ ...e, bloom: !e.bloom }))}>
Toggle Bloom
</button>
<button onClick={() => setEffects(e => ({ ...e, vignette: !e.vignette }))}>
Toggle Vignette
</button>
<button onClick={() => setEffects(e => ({ ...e, glitch: !e.glitch }))}>
Toggle Glitch
</button>
</div>
</>
)
}tsx
import { useState } from 'react'
import { EffectComposer, Bloom, Vignette, Glitch } from '@react-three/postprocessing'
function ConditionalPostProcessing() {
const [effects, setEffects] = useState({
bloom: true,
vignette: true,
glitch: false,
})
return (
<>
<EffectComposer>
{effects.bloom && (
<Bloom intensity={1.5} luminanceThreshold={0.9} />
)}
{effects.vignette && (
<Vignette offset={0.5} darkness={0.5} />
)}
{effects.glitch && (
<Glitch delay={[1, 3]} duration={[0.5, 1]} strength={[0.3, 1]} />
)}
</EffectComposer>
{/* 用于切换特效的UI */}
<div className="controls">
<button onClick={() => setEffects(e => ({ ...e, bloom: !e.bloom }))}>
切换发光效果
</button>
<button onClick={() => setEffects(e => ({ ...e, vignette: !e.vignette }))}>
切换暗角效果
</button>
<button onClick={() => setEffects(e => ({ ...e, glitch: !e.glitch }))}>
切换故障效果
</button>
</div>
</>
)
}Animated Effects
动画特效
tsx
import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
import { EffectComposer, Bloom, ChromaticAberration } from '@react-three/postprocessing'
function AnimatedEffects() {
const bloomRef = useRef()
const chromaticRef = useRef()
useFrame(({ clock }) => {
const t = clock.elapsedTime
// Animate bloom intensity
if (bloomRef.current) {
bloomRef.current.intensity = 1 + Math.sin(t) * 0.5
}
// Animate chromatic aberration
if (chromaticRef.current) {
const offset = Math.sin(t * 2) * 0.002
chromaticRef.current.offset.set(offset, offset)
}
})
return (
<EffectComposer>
<Bloom ref={bloomRef} luminanceThreshold={0.9} />
<ChromaticAberration ref={chromaticRef} />
</EffectComposer>
)
}tsx
import { useRef } from 'react'
import { useFrame } from '@react-three/fiber'
import { EffectComposer, Bloom, ChromaticAberration } from '@react-three/postprocessing'
function AnimatedEffects() {
const bloomRef = useRef()
const chromaticRef = useRef()
useFrame(({ clock }) => {
const t = clock.elapsedTime
// 动画化发光强度
if (bloomRef.current) {
bloomRef.current.intensity = 1 + Math.sin(t) * 0.5
}
// 动画化色差效果
if (chromaticRef.current) {
const offset = Math.sin(t * 2) * 0.002
chromaticRef.current.offset.set(offset, offset)
}
})
return (
<EffectComposer>
<Bloom ref={bloomRef} luminanceThreshold={0.9} />
<ChromaticAberration ref={chromaticRef} />
</EffectComposer>
)
}N8AO (High Quality AO)
N8AO(高质量环境光遮蔽)
tsx
import { EffectComposer } from '@react-three/postprocessing'
import { N8AO } from '@react-three/postprocessing'
<EffectComposer>
<N8AO
aoRadius={0.5}
intensity={1}
aoSamples={6}
denoiseSamples={4}
denoiseRadius={12}
distanceFalloff={1}
color="black"
quality="low" // low, medium, high, ultra
halfRes={false}
/>
</EffectComposer>tsx
import { EffectComposer } from '@react-three/postprocessing'
import { N8AO } from '@react-three/postprocessing'
<EffectComposer>
<N8AO
aoRadius={0.5}
intensity={1}
aoSamples={6}
denoiseSamples={4}
denoiseRadius={12}
distanceFalloff={1}
color="black"
quality="low" // 可选:low, medium, high, ultra
halfRes={false}
/>
</EffectComposer>God Rays
体积光(God Rays)
tsx
import { EffectComposer, GodRays } from '@react-three/postprocessing'
import { useRef } from 'react'
function Scene() {
const sunRef = useRef()
return (
<Canvas>
{/* Sun mesh (light source for god rays) */}
<mesh ref={sunRef} position={[0, 5, -10]}>
<sphereGeometry args={[1]} />
<meshBasicMaterial color="#ffddaa" />
</mesh>
<EffectComposer>
{sunRef.current && (
<GodRays
sun={sunRef}
blendFunction={BlendFunction.SCREEN}
samples={60}
density={0.96}
decay={0.9}
weight={0.4}
exposure={0.6}
clampMax={1}
blur
/>
)}
</EffectComposer>
</Canvas>
)
}tsx
import { EffectComposer, GodRays } from '@react-three/postprocessing'
import { useRef } from 'react'
function Scene() {
const sunRef = useRef()
return (
<Canvas>
{/* 太阳网格(体积光的光源) */}
<mesh ref={sunRef} position={[0, 5, -10]}>
<sphereGeometry args={[1]} />
<meshBasicMaterial color="#ffddaa" />
</mesh>
<EffectComposer>
{sunRef.current && (
<GodRays
sun={sunRef}
blendFunction={BlendFunction.SCREEN}
samples={60}
density={0.96}
decay={0.9}
weight={0.4}
exposure={0.6}
clampMax={1}
blur
/>
)}
</EffectComposer>
</Canvas>
)
}LUT (Color Lookup Table)
LUT(色彩查找表)
tsx
import { EffectComposer, LUT } from '@react-three/postprocessing'
import { LUTCubeLoader } from 'postprocessing'
import { useLoader } from '@react-three/fiber'
function ColorGradedScene() {
const texture = useLoader(LUTCubeLoader, '/luts/cinematic.cube')
return (
<EffectComposer>
<LUT lut={texture} />
</EffectComposer>
)
}tsx
import { EffectComposer, LUT } from '@react-three/postprocessing'
import { LUTCubeLoader } from 'postprocessing'
import { useLoader } from '@react-three/fiber'
function ColorGradedScene() {
const texture = useLoader(LUTCubeLoader, '/luts/cinematic.cube')
return (
<EffectComposer>
<LUT lut={texture} />
</EffectComposer>
)
}Blend Functions
混合函数
tsx
import { BlendFunction } from 'postprocessing'
// Available blend functions:
BlendFunction.SKIP // Skip blending
BlendFunction.ADD // Additive
BlendFunction.ALPHA // Alpha
BlendFunction.AVERAGE // Average
BlendFunction.COLOR // Color
BlendFunction.COLOR_BURN // Color Burn
BlendFunction.COLOR_DODGE // Color Dodge
BlendFunction.DARKEN // Darken
BlendFunction.DIFFERENCE // Difference
BlendFunction.DIVIDE // Divide
BlendFunction.DST // Destination
BlendFunction.EXCLUSION // Exclusion
BlendFunction.HARD_LIGHT // Hard Light
BlendFunction.HARD_MIX // Hard Mix
BlendFunction.HUE // Hue
BlendFunction.INVERT // Invert
BlendFunction.INVERT_RGB // Invert RGB
BlendFunction.LIGHTEN // Lighten
BlendFunction.LINEAR_BURN // Linear Burn
BlendFunction.LINEAR_DODGE // Linear Dodge
BlendFunction.LINEAR_LIGHT // Linear Light
BlendFunction.LUMINOSITY // Luminosity
BlendFunction.MULTIPLY // Multiply
BlendFunction.NEGATION // Negation
BlendFunction.NORMAL // Normal
BlendFunction.OVERLAY // Overlay
BlendFunction.PIN_LIGHT // Pin Light
BlendFunction.REFLECT // Reflect
BlendFunction.SATURATION // Saturation
BlendFunction.SCREEN // Screen
BlendFunction.SET // Set
BlendFunction.SOFT_LIGHT // Soft Light
BlendFunction.SRC // Source
BlendFunction.SUBTRACT // Subtract
BlendFunction.VIVID_LIGHT // Vivid Lighttsx
import { BlendFunction } from 'postprocessing'
// 可用的混合函数:
BlendFunction.SKIP // 跳过混合
BlendFunction.ADD // 加法混合
BlendFunction.ALPHA // 透明度混合
BlendFunction.AVERAGE // 平均混合
BlendFunction.COLOR // 颜色混合
BlendFunction.COLOR_BURN // 颜色加深
BlendFunction.COLOR_DODGE // 颜色减淡
BlendFunction.DARKEN // 变暗混合
BlendFunction.DIFFERENCE // 差值混合
BlendFunction.DIVIDE // 除法混合
BlendFunction.DST // 目标色混合
BlendFunction.EXCLUSION // 排除混合
BlendFunction.HARD_LIGHT // 强光混合
BlendFunction.HARD_MIX // 实色混合
BlendFunction.HUE // 色相混合
BlendFunction.INVERT // 反相混合
BlendFunction.INVERT_RGB // RGB反相混合
BlendFunction.LIGHTEN // 变亮混合
BlendFunction.LINEAR_BURN // 线性加深
BlendFunction.LINEAR_DODGE // 线性减淡
BlendFunction.LINEAR_LIGHT // 线性光混合
BlendFunction.LUMINOSITY // 亮度混合
BlendFunction.MULTIPLY // 正片叠底
BlendFunction.NEGATION // 否定混合
BlendFunction.NORMAL // 正常混合
BlendFunction.OVERLAY // 叠加混合
BlendFunction.PIN_LIGHT // 点光混合
BlendFunction.REFLECT // 反射混合
BlendFunction.SATURATION // 饱和度混合
BlendFunction.SCREEN // 滤色混合
BlendFunction.SET // 设置混合
BlendFunction.SOFT_LIGHT // 柔光混合
BlendFunction.SRC // 源色混合
BlendFunction.SUBTRACT // 减法混合
BlendFunction.VIVID_LIGHT // 亮光混合Performance Tips
性能优化技巧
- Limit effect count: Each effect adds rendering overhead
- Use multisampling wisely: Higher values = slower performance
- Disable when not needed: Toggle prop
enabled - Lower resolution: Some effects have resolution props
- Profile with DevTools: Monitor GPU usage
tsx
// Disable all effects
<EffectComposer enabled={performanceMode}>
...
</EffectComposer>
// Reduce effect quality on mobile
const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent)
<EffectComposer multisampling={isMobile ? 0 : 8}>
<Bloom mipmapBlur={!isMobile} radius={isMobile ? 0.4 : 0.8} />
{!isMobile && <SSAO samples={16} />}
</EffectComposer>- 限制特效数量:每个特效都会增加渲染开销
- 合理使用多重采样:采样值越高,性能越差
- 不需要时禁用:使用属性切换
enabled - 降低分辨率:部分特效提供分辨率配置项
- 使用开发者工具分析:监控GPU使用率
tsx
// 禁用所有特效
<EffectComposer enabled={performanceMode}>
...
</EffectComposer>
// 在移动端降低特效质量
const isMobile = /iPhone|iPad|Android/i.test(navigator.userAgent)
<EffectComposer multisampling={isMobile ? 0 : 8}>
<Bloom mipmapBlur={!isMobile} radius={isMobile ? 0.4 : 0.8} />
{!isMobile && <SSAO samples={16} />}
</EffectComposer>See Also
相关链接
- - Custom shader development
r3f-shaders - - Emissive materials for bloom
r3f-materials - - Canvas and renderer setup
r3f-fundamentals
- - 自定义着色器开发
r3f-shaders - - 用于发光效果的自发光材质
r3f-materials - - Canvas和渲染器设置
r3f-fundamentals