241 lines
5.3 KiB
Markdown
241 lines
5.3 KiB
Markdown
# Post-Processing
|
|
|
|
Apply visual effects after rendering.
|
|
|
|
## EffectComposer Setup
|
|
|
|
Post-processing pipeline (addon):
|
|
|
|
```javascript
|
|
import { EffectComposer } from 'three/addons/postprocessing/EffectComposer.js';
|
|
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
|
|
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
|
|
|
|
// Create composer
|
|
const composer = new EffectComposer(renderer);
|
|
|
|
// Add render pass (required first pass)
|
|
const renderPass = new RenderPass(scene, camera);
|
|
composer.addPass(renderPass);
|
|
|
|
// Add effect passes
|
|
// ... (see below)
|
|
|
|
// Add output pass (required last pass)
|
|
const outputPass = new OutputPass();
|
|
composer.addPass(outputPass);
|
|
|
|
// Render with composer instead of renderer
|
|
function animate() {
|
|
requestAnimationFrame(animate);
|
|
composer.render();
|
|
}
|
|
|
|
// Handle resize
|
|
window.addEventListener('resize', () => {
|
|
composer.setSize(window.innerWidth, window.innerHeight);
|
|
});
|
|
```
|
|
|
|
## Bloom Effect
|
|
|
|
Glow effect for bright areas:
|
|
|
|
```javascript
|
|
import { UnrealBloomPass } from 'three/addons/postprocessing/UnrealBloomPass.js';
|
|
|
|
const bloomPass = new UnrealBloomPass(
|
|
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
|
1.5, // strength
|
|
0.4, // radius
|
|
0.85 // threshold (brightness trigger)
|
|
);
|
|
composer.addPass(bloomPass);
|
|
|
|
// Adjust parameters
|
|
bloomPass.strength = 2.0;
|
|
bloomPass.radius = 1.0;
|
|
bloomPass.threshold = 0.5;
|
|
```
|
|
|
|
## SSAO (Screen Space Ambient Occlusion)
|
|
|
|
Realistic shadowing in crevices:
|
|
|
|
```javascript
|
|
import { SSAOPass } from 'three/addons/postprocessing/SSAOPass.js';
|
|
|
|
const ssaoPass = new SSAOPass(scene, camera, width, height);
|
|
ssaoPass.kernelRadius = 16;
|
|
ssaoPass.minDistance = 0.005;
|
|
ssaoPass.maxDistance = 0.1;
|
|
composer.addPass(ssaoPass);
|
|
```
|
|
|
|
## SSR (Screen Space Reflections)
|
|
|
|
Real-time reflections:
|
|
|
|
```javascript
|
|
import { SSRPass } from 'three/addons/postprocessing/SSRPass.js';
|
|
|
|
const ssrPass = new SSRPass({
|
|
renderer,
|
|
scene,
|
|
camera,
|
|
width: window.innerWidth,
|
|
height: window.innerHeight
|
|
});
|
|
|
|
ssrPass.opacity = 0.5;
|
|
ssrPass.maxDistance = 0.1;
|
|
composer.addPass(ssrPass);
|
|
```
|
|
|
|
## Depth of Field (Bokeh)
|
|
|
|
Blur based on depth:
|
|
|
|
```javascript
|
|
import { BokehPass } from 'three/addons/postprocessing/BokehPass.js';
|
|
|
|
const bokehPass = new BokehPass(scene, camera, {
|
|
focus: 10.0, // focal distance
|
|
aperture: 0.025, // blur amount
|
|
maxblur: 0.01 // max blur size
|
|
});
|
|
composer.addPass(bokehPass);
|
|
```
|
|
|
|
## FXAA (Anti-Aliasing)
|
|
|
|
Smooth jagged edges:
|
|
|
|
```javascript
|
|
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
|
|
import { FXAAShader } from 'three/addons/shaders/FXAAShader.js';
|
|
|
|
const fxaaPass = new ShaderPass(FXAAShader);
|
|
fxaaPass.material.uniforms['resolution'].value.x = 1 / window.innerWidth;
|
|
fxaaPass.material.uniforms['resolution'].value.y = 1 / window.innerHeight;
|
|
composer.addPass(fxaaPass);
|
|
```
|
|
|
|
## Outline Pass
|
|
|
|
Highlight selected objects:
|
|
|
|
```javascript
|
|
import { OutlinePass } from 'three/addons/postprocessing/OutlinePass.js';
|
|
|
|
const outlinePass = new OutlinePass(
|
|
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
|
scene,
|
|
camera
|
|
);
|
|
|
|
outlinePass.edgeStrength = 3;
|
|
outlinePass.edgeGlow = 0.5;
|
|
outlinePass.edgeThickness = 1;
|
|
outlinePass.visibleEdgeColor.set('#ffffff');
|
|
outlinePass.hiddenEdgeColor.set('#190a05');
|
|
|
|
// Set objects to outline
|
|
outlinePass.selectedObjects = [mesh1, mesh2];
|
|
|
|
composer.addPass(outlinePass);
|
|
```
|
|
|
|
## Film/Grain Effect
|
|
|
|
Add film grain and scanlines:
|
|
|
|
```javascript
|
|
import { FilmPass } from 'three/addons/postprocessing/FilmPass.js';
|
|
|
|
const filmPass = new FilmPass(
|
|
0.35, // noise intensity
|
|
0.5, // scanline intensity
|
|
648, // scanline count
|
|
false // grayscale
|
|
);
|
|
composer.addPass(filmPass);
|
|
```
|
|
|
|
## Glitch Effect
|
|
|
|
Digital glitch distortion:
|
|
|
|
```javascript
|
|
import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';
|
|
|
|
const glitchPass = new GlitchPass();
|
|
composer.addPass(glitchPass);
|
|
```
|
|
|
|
## Custom Shader Pass
|
|
|
|
Create custom effects:
|
|
|
|
```javascript
|
|
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
|
|
|
|
const customShader = {
|
|
uniforms: {
|
|
tDiffuse: { value: null },
|
|
amount: { value: 1.0 }
|
|
},
|
|
vertexShader: `
|
|
varying vec2 vUv;
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
}
|
|
`,
|
|
fragmentShader: `
|
|
uniform sampler2D tDiffuse;
|
|
uniform float amount;
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vec4 color = texture2D(tDiffuse, vUv);
|
|
// Apply custom effect
|
|
color.r *= amount;
|
|
gl_FragColor = color;
|
|
}
|
|
`
|
|
};
|
|
|
|
const customPass = new ShaderPass(customShader);
|
|
customPass.material.uniforms.amount.value = 1.5;
|
|
composer.addPass(customPass);
|
|
```
|
|
|
|
## Common Pass Patterns
|
|
|
|
```javascript
|
|
// Combine multiple effects
|
|
composer.addPass(renderPass);
|
|
composer.addPass(ssaoPass);
|
|
composer.addPass(bloomPass);
|
|
composer.addPass(fxaaPass);
|
|
composer.addPass(outputPass);
|
|
|
|
// Selective rendering
|
|
bloomPass.renderToScreen = false; // render to texture, not screen
|
|
|
|
// Clear pass
|
|
import { ClearPass } from 'three/addons/postprocessing/ClearPass.js';
|
|
const clearPass = new ClearPass();
|
|
composer.addPass(clearPass);
|
|
```
|
|
|
|
## Performance Tips
|
|
|
|
- Post-processing is GPU-intensive
|
|
- Use lower resolution for expensive effects (SSAO, SSR)
|
|
- Limit number of passes (3-5 for good performance)
|
|
- Disable passes when not needed
|
|
- Use FXAA instead of MSAA (cheaper)
|
|
- Test on target devices
|