Reputation: 21
I'm new the the glsl shaders in three.js, now trying to make simple and fast blur effect on a mesh texture. This is my fragment shader code:
void blurh(in vec4 inh, out vec4 outh, int r) {
for(int x = -r; x < r+1; x++) {
float coordx = vUv[0] + float(x) / uResolution[0];
coordx = max(0.0, min(1.0, coordx));
inh += texture2D(uTexture, vec2 (coordx, vUv[1]));
}
outh = inh / float(r + r + 1);
}
void blurv(in vec4 inv, out vec4 outv, int r) {
for(int y = -r; y < r+1; y++) {
float coordy = vUv[1] + float(y) / uResolution[1];
coordy = max(0.0, min(1.0, coordy));
inv += texture2D(uTexture, vec2 (vUv[0], coordy));
}
outv = inv / float(r + r + 1);
}
void main() {
int r = 200; // radius
gl_FragColor = texture2D(uTexture, vUv);
blurh(gl_FragColor, gl_FragColor, r);
blurv(gl_FragColor, gl_FragColor, r);
}
Upvotes: 1
Views: 486
Reputation: 31076
Notice that the repository already provides blur shaders. So you can use the post-processing pipeline to achieve the intended effect:
let camera, scene, composer;
let mesh;
init();
animate();
function init() {
camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
camera.position.z = 1;
scene = new THREE.Scene();
const geometry = new THREE.BoxGeometry(0.2, 0.2, 0.2);
const material = new THREE.MeshNormalMaterial();
mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
composer = new THREE.EffectComposer(renderer);
const renderPass = new THREE.RenderPass(scene, camera);
const effectHBlur = new THREE.ShaderPass(THREE.HorizontalBlurShader);
const effectVBlur = new THREE.ShaderPass(THREE.VerticalBlurShader);
effectHBlur.uniforms['h'].value = 1 / window.innerWidth;
effectVBlur.uniforms['v'].value = 1 / window.innerHeight;
composer.addPass(renderPass);
composer.addPass(effectHBlur);
composer.addPass(effectVBlur);
}
function animate() {
requestAnimationFrame(animate);
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.02;
composer.render();
}
body {
margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/HorizontalBlurShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/VerticalBlurShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/shaders/CopyShader.js"></script>
If you don't want to use the effect composer, you have to work with plain render targets. Meaning:
So you have to split your current shader into two.
Upvotes: 2