packages/polaris/polaris-three/src/renderer/pipeline/pass/BlurPass.js (76 lines of code) (raw):
import Pass from '../Pass'
import fs from './glsl/blur_fs.glsl'
import vs from './glsl/blur_vs.glsl'
import CanvasMesh from '../CanvasMesh'
import { WebGLRenderTarget, Vector2, Scene } from 'three'
/**
* The Kawase blur kernel presets.
*
* @type {Float32Array[]}
* @private
*/
const kernelPresets = [
[0.0, 0.0],
[0.0, 1.0, 1.0],
[0.0, 1.0, 1.0, 2.0],
[0.0, 1.0, 2.0, 2.0, 3.0],
[0.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0],
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 8.0, 9.0, 10.0],
]
const defaultConf = {
width: 1200,
height: 800,
kernel: 3,
}
export default class BlurPass extends Pass {
constructor(conf) {
super(conf)
this.kernel = conf.kernel === undefined ? defaultConf.kernel : conf.kernel
this.kernels = kernelPresets[this.kernel]
this.proTargetX = new WebGLRenderTarget(this.width / 2, this.height / 2)
this.proTargetY = new WebGLRenderTarget(this.width / 2, this.height / 2)
this.texelSize = new Vector2(1 / this.width, 1 / this.height)
this.halfTexelSize = this.texelSize.clone().multiplyScalar(0.5)
this.kernelScene = new Scene()
this.kernelMesh = new CanvasMesh({
customVs: vs,
customFs: fs,
uniforms: {
texelSize: { value: this.texelSize },
halfTexelSize: { value: this.halfTexelSize },
kernel: { value: 0 },
tex: {},
},
})
this.kernelScene.add(this.kernelMesh.mesh)
}
render(renderer) {
// 收到原始图像的尺寸应该是完整的(this.width等于原始width)
// 首先拷贝到一个一半分辨率target上,进行接下来的处理
// 这里的Scene里面只包含普通CanvasMesh
renderer.setRenderTarget(this.proTargetX)
renderer.render(this.scene, this.camera)
let readTarget = this.proTargetX
let writeTarget = this.proTargetY
// kernel 卷积
this.kernels.forEach((kernel, index) => {
this.kernelMesh.material.uniforms.kernel.value = kernel
this.kernelMesh.material.uniforms.tex.value = readTarget.texture
if (index === this.kernels.length - 1) {
renderer.setRenderTarget(this.output)
renderer.render(this.kernelScene, this.camera)
return
}
renderer.setRenderTarget(writeTarget)
renderer.render(this.kernelScene, this.camera)
const tmp = writeTarget
writeTarget = readTarget
readTarget = tmp
})
// 最后的writeTarget中保存着最新的卷积结果
// renderer.render(this.scene, this.camera, this.renderTarget);
}
resize(width, height) {
this.width = width
this.height = height
this.texelSize.set(1 / this.width, 1 / this.height)
this.halfTexelSize.copy(this.texelSize).multiplyScalar(0.5)
this.proTargetX.setSize(this.width / 2, this.height / 2)
this.proTargetY.setSize(this.width / 2, this.height / 2)
}
dispose() {
super.dispose()
this.proTargetX.dispose()
this.proTargetY.dispose()
this.kernelMesh.material.dispose()
this.kernelMesh.geometry.dispose()
}
}