UNPKG

lume

Version:

Build next-level interactive web applications.

125 lines 5.8 kB
import { Scene } from 'three/src/scenes/Scene.js'; import { OrthographicCamera } from 'three/src/cameras/OrthographicCamera.js'; import { WebGLRenderTarget } from 'three/src/renderers/WebGLRenderTarget.js'; import { Mesh, PlaneGeometry, Vector2 } from 'three/src/Three.js'; import { TriangleBlurShader } from 'three/examples/jsm/shaders/TriangleBlurShader.js'; import { ShaderMaterial } from 'three/src/materials/ShaderMaterial.js'; import { HorizontalBlurShader } from 'three/examples/jsm/shaders/HorizontalBlurShader.js'; import { VerticalBlurShader } from 'three/examples/jsm/shaders/VerticalBlurShader.js'; import { Scene as ThreeScene } from 'three/src/scenes/Scene.js'; import { UniformsUtils } from 'three/src/renderers/shaders/UniformsUtils.js'; export function triangleBlurTexture(renderer, texture, blur = 0.1, passes = 1, iterations = 10) { const width = texture.image.width; const height = texture.image.height; // renderer = new WebGLRenderer() const cameraRTT = new OrthographicCamera(-1, 1, 1, -1, 0, 1); const sceneRTT = new Scene(); // render targets const renderTarget1 = new WebGLRenderTarget(width, height); const renderTarget2 = new WebGLRenderTarget(width, height); // shader materials const shader = makeTriangleBlurShader(iterations); const blurMaterial = new ShaderMaterial({ vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, uniforms: UniformsUtils.clone(shader.uniforms), }); blurMaterial.uniforms.delta.value = new Vector2(1, 1); // fullscreen quad const planeGeometry = new PlaneGeometry(2, 2); const fullScreenQuad = new Mesh(planeGeometry, blurMaterial); sceneRTT.add(fullScreenQuad); // passes let lastTexture = texture; while (passes--) { // vertical pass blurMaterial.uniforms.blurTexture.value = lastTexture; blurMaterial.uniforms.delta.value = new Vector2(blur, 0); renderer.setRenderTarget(renderTarget1); renderer.render(sceneRTT, cameraRTT); renderer.setRenderTarget(null); lastTexture = renderTarget1.texture; // horizontal pass blurMaterial.uniforms.blurTexture.value = lastTexture; blurMaterial.uniforms.delta.value = new Vector2(0, blur); renderer.setRenderTarget(renderTarget2); renderer.render(sceneRTT, cameraRTT); renderer.setRenderTarget(null); lastTexture = renderTarget2.texture; } // return lastTexture; } export function makeTriangleBlurShader(iterations = 10) { // Remove texture, because texture is a reserved word in WebGL 2 const { texture, ...uniforms } = TriangleBlurShader.uniforms; const TriangleBlurShader2 = { ...TriangleBlurShader, name: 'TriangleBlurShader2', uniforms: { ...uniforms, // Replace texture with blurTexture for WebGL 2 blurTexture: { value: null }, }, }; // Replace texture with blurTexture for WebGL 2 TriangleBlurShader2.fragmentShader = TriangleBlurShader2.fragmentShader.replace('uniform sampler2D texture;', 'uniform sampler2D blurTexture;'); TriangleBlurShader2.fragmentShader = TriangleBlurShader2.fragmentShader.replace('texture2D( texture', 'texture2D( blurTexture'); // Make iterations configurable. TriangleBlurShader2.fragmentShader = TriangleBlurShader2.fragmentShader.replace('#define ITERATIONS 10.0', '#define ITERATIONS ' + iterations + '.0'); return TriangleBlurShader2; } /** * Apply a simple vertical/horizontal Gaussian blur to a texture. The simple * design can make the blurred image seem like it was previously pixelated. * `triangleBlurTexture` offers a better blur but may also cost more. * * Adapted from https://discourse.threejs.org/t/39433 */ export function verticalHorizontalGaussianBlurTexture(renderer, texture, passes = 1) { const width = texture.image.width; const height = texture.image.height; const cameraRTT = new OrthographicCamera(-1, 1, 1, -1, 0, 1); const sceneRTT = new ThreeScene(); // render targets const renderTarget1 = new WebGLRenderTarget(width, height); const renderTarget2 = new WebGLRenderTarget(width, height); // shader materials const hBlurMaterial = new ShaderMaterial({ vertexShader: HorizontalBlurShader.vertexShader, fragmentShader: HorizontalBlurShader.fragmentShader, uniforms: UniformsUtils.clone(HorizontalBlurShader.uniforms), }); hBlurMaterial.uniforms.h.value = 1 / width; const vBlurMaterial = new ShaderMaterial({ vertexShader: VerticalBlurShader.vertexShader, fragmentShader: VerticalBlurShader.fragmentShader, uniforms: UniformsUtils.clone(VerticalBlurShader.uniforms), }); vBlurMaterial.uniforms.v.value = 1 / height; // fullscreen quad const planeGeometry = new PlaneGeometry(2, 2); const fullScreenQuad = new Mesh(planeGeometry, hBlurMaterial); sceneRTT.add(fullScreenQuad); // passes let lastTexture = texture; while (passes--) { // horizontal pass fullScreenQuad.material = hBlurMaterial; hBlurMaterial.uniforms.tDiffuse.value = lastTexture; renderer.setRenderTarget(renderTarget1); renderer.render(sceneRTT, cameraRTT); renderer.setRenderTarget(null); lastTexture = renderTarget1.texture; // vertical pass fullScreenQuad.material = vBlurMaterial; vBlurMaterial.uniforms.tDiffuse.value = lastTexture; renderer.setRenderTarget(renderTarget2); renderer.render(sceneRTT, cameraRTT); renderer.setRenderTarget(null); lastTexture = renderTarget2.texture; } // return renderTarget2.texture; } //# sourceMappingURL=texture-blur.js.map