post processing
This commit is contained in:
121
app/src/motion-blur.ts
Normal file
121
app/src/motion-blur.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import * as THREE from 'three'
|
||||
|
||||
export class MotionBlurEffect {
|
||||
private scene: THREE.Scene
|
||||
private camera: THREE.PerspectiveCamera
|
||||
private renderer: THREE.WebGLRenderer
|
||||
private renderTarget1: THREE.WebGLRenderTarget
|
||||
private renderTarget2: THREE.WebGLRenderTarget
|
||||
private blurMaterial: THREE.ShaderMaterial
|
||||
private quad: THREE.Mesh
|
||||
private intensity: number = 0.5
|
||||
private accumulation: number = 0.8
|
||||
|
||||
constructor(
|
||||
scene: THREE.Scene,
|
||||
camera: THREE.PerspectiveCamera,
|
||||
renderer: THREE.WebGLRenderer
|
||||
) {
|
||||
this.scene = scene
|
||||
this.camera = camera
|
||||
this.renderer = renderer
|
||||
|
||||
const size = renderer.getSize(new THREE.Vector2())
|
||||
|
||||
// Create render targets for accumulation
|
||||
this.renderTarget1 = new THREE.WebGLRenderTarget(size.x, size.y, {
|
||||
minFilter: THREE.LinearFilter,
|
||||
magFilter: THREE.LinearFilter,
|
||||
format: THREE.RGBAFormat,
|
||||
type: THREE.FloatType
|
||||
})
|
||||
|
||||
this.renderTarget2 = new THREE.WebGLRenderTarget(size.x, size.y, {
|
||||
minFilter: THREE.LinearFilter,
|
||||
magFilter: THREE.LinearFilter,
|
||||
format: THREE.RGBAFormat,
|
||||
type: THREE.FloatType
|
||||
})
|
||||
|
||||
// Motion blur shader material
|
||||
this.blurMaterial = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
tCurrent: { value: null },
|
||||
tPrevious: { value: null },
|
||||
intensity: { value: this.intensity },
|
||||
accumulation: { value: this.accumulation }
|
||||
},
|
||||
vertexShader: `
|
||||
varying vec2 vUv;
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
uniform sampler2D tCurrent;
|
||||
uniform sampler2D tPrevious;
|
||||
uniform float intensity;
|
||||
uniform float accumulation;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vec4 current = texture2D(tCurrent, vUv);
|
||||
vec4 previous = texture2D(tPrevious, vUv);
|
||||
|
||||
// Blend current frame with accumulated previous frames
|
||||
vec4 result = mix(current, previous, accumulation * intensity);
|
||||
|
||||
gl_FragColor = result;
|
||||
}
|
||||
`
|
||||
})
|
||||
|
||||
// Create fullscreen quad
|
||||
const geometry = new THREE.PlaneGeometry(2, 2)
|
||||
this.quad = new THREE.Mesh(geometry, this.blurMaterial)
|
||||
}
|
||||
|
||||
public render(deltaTime: number): THREE.WebGLRenderTarget {
|
||||
// Render current frame to renderTarget1
|
||||
this.renderer.setRenderTarget(this.renderTarget1)
|
||||
this.renderer.render(this.scene, this.camera)
|
||||
|
||||
// Apply motion blur by blending with previous frame
|
||||
this.blurMaterial.uniforms.tCurrent.value = this.renderTarget1.texture
|
||||
this.blurMaterial.uniforms.tPrevious.value = this.renderTarget2.texture
|
||||
|
||||
// Render blurred result to renderTarget2
|
||||
this.renderer.setRenderTarget(this.renderTarget2)
|
||||
this.renderer.render(this.quad, new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1))
|
||||
|
||||
// Swap render targets for next frame
|
||||
const temp = this.renderTarget1
|
||||
this.renderTarget1 = this.renderTarget2
|
||||
this.renderTarget2 = temp
|
||||
|
||||
return this.renderTarget1
|
||||
}
|
||||
|
||||
public setIntensity(intensity: number): void {
|
||||
this.intensity = intensity
|
||||
this.blurMaterial.uniforms.intensity.value = intensity
|
||||
}
|
||||
|
||||
public setAccumulation(accumulation: number): void {
|
||||
this.accumulation = accumulation
|
||||
this.blurMaterial.uniforms.accumulation.value = accumulation
|
||||
}
|
||||
|
||||
public resize(width: number, height: number): void {
|
||||
this.renderTarget1.setSize(width, height)
|
||||
this.renderTarget2.setSize(width, height)
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this.renderTarget1.dispose()
|
||||
this.renderTarget2.dispose()
|
||||
this.blurMaterial.dispose()
|
||||
this.quad.geometry.dispose()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user