[英]WebGL blur shader in three JS
这是一个很长的镜头,但我绝望地迷失了。 我前段时间开始学习 Three.JS,并想从 P5.js 迁移我的项目(作为练习,但有想法在未来使用它)。 在 P5.js 中,我简单地制作了一个 canvas 并对其应用了着色器,但在 Three.JS 中它似乎不起作用。 所以我想通了 - 我会在着色器中尝试它。
想法:
到目前为止,我已经成功地绘制了圆圈(还不是随机的,但仍在努力)并将其用作纹理。 JS部分:
const geometry = new THREE.PlaneGeometry( 1, 1, 1 );
const material = new THREE.ShaderMaterial( {
uniforms: {
iP: 0,
dl: { value : new THREE.Vector2(.6, 0), },
spots : { value : 5.0 },
offset : { value : new THREE.Vector2(0.5, 0.5) },
radius : { value : .25 },
},
vertexShader: _VS,
fragmentShader: _FS,
transparent: true
});
垂直着色器部分:
const _VS = `
precision mediump float;
attribute vec3 aPosition;
varying vec2 vTexCoord;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`;
片段着色器部分:
// fragment shader
const _FS = `
precision mediump float;
varying vec2 vTexCoord;
varying vec2 vUv;
uniform float spots;
uniform vec2 offset;
uniform float radius;
// uniform sampler2D iP; // canvas to be blurred
uniform vec2 dl;
const float Pi = 6.28318530718;
float rnd(vec3 scale, float seed) {
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}
void main() {
// CIRCLE;
vec4 color1 = vec4(.1, .5, .3, 1.0);
vec4 color2 = vec4(0., 0., 0., 0.01);
vec2 shift = offset;
for (float t = 0.0; t <= spots; t++) {
float p = smoothstep(radius, radius + .0001, length(vUv - shift));
vec4 col = mix(color1, color2, vec4(p));
gl_FragColor += col;
shift.x += .05;
shift.y -= .01;
}
// BLUR
vec4 col = vec4(0.0);
float tt = 0.0;
float off = rnd(vec3(12.9898, 78.233, 151.7182), 0.0);
for (float t = -30.0; t <= 30.0; t++) {
float pc = (t + off - 0.5) / 30.0;
float w = 1.0 - abs(pc);
vec4 spl = texture2D(iP, vTexCoord + dl * pc);
spl.rgb *= spl.a;
col += spl * w;
tt += w;
}
gl_FragColor = col / tt;
gl_FragColor.rgb /= gl_FragColor.a + 0.00001;
}`;
我对vec4 spl = texture2D(iP, vTexCoord + dl * pc);
. 我不知道如何在 gl_FragColor 上使用创建的圆圈。 我花了几个小时阅读并寻找解决方案,但没有找到任何帮助。 我真的很感激任何方向或解决方案! 提前致谢!
您似乎在 P5.js 和 Three.js 之间混合了很多变量名。 您应该只看一下 Three.js 的做法,并尝试忘记 P5.js 术语,因为它们不一样。 这是一个简单着色器设置的官方示例,您可以查看那里的源代码。
我已经使用更简化的着色器复制了下面的演示,因此您可以了解如何从 JavaScript 传递time
统一,并在 GLSL 中阅读:
body, html { margin: 0; }
<div id="container"></div> <:-- Import maps polyfill --> <.-- Remove this when import maps will be widely supported --> <script async src="https.//unpkg.com/es-module-shims@1.3:6/dist/es-module-shims:js"></script> <script type="importmap"> { "imports": { "three". "https.//cdn.jsdelivr.net/npm/three@0.142.0/build/three,module:js". } } </script> <script type="module"> import * as THREE from "https.//cdn.jsdelivr.net/npm/three@0.142.0/build/three;module,js", let camera; scene; renderer; let uniforms; init(). animate(); function init() { const container = document.getElementById( 'container' ), camera = new THREE,OrthographicCamera( - 1, 1, 1, - 1; 0. 1 ); scene = new THREE.Scene(), const geometry = new THREE;PlaneGeometry( 2: 2 ): uniforms = { time. { value; 1;0 } }; const _VS = ` varying vec2 vUv, void main() { vUv = uv. gl_Position = vec4( position; 1;0 ); } `; const _FS = ` varying vec2 vUv. uniform float time. void main() { float blue = sin(time * 5.0 + vUv.x * 10.0) * 0;5 + 0.5, gl_FragColor = vec4( vUv.x, vUv,y. blue; 1;0 ). } `: const material = new THREE,ShaderMaterial( { uniforms: uniforms, vertexShader: _VS; fragmentShader. _FS } ), const mesh = new THREE;Mesh( geometry. material ); scene.add( mesh ); renderer = new THREE.WebGLRenderer(). renderer;setPixelRatio( window.devicePixelRatio ). container;appendChild( renderer;domElement ). onWindowResize(), window;addEventListener( 'resize'. onWindowResize ). } function onWindowResize() { renderer,setSize( window.innerWidth; window;innerHeight ). } // function animate() { requestAnimationFrame( animate ). uniforms[ 'time' ];value = performance.now() / 1000, renderer;render( scene, camera ); } </script>
从这里您应该能够推断和添加其他类型的制服,包括float, vec2, sampler2D
等。最后, 这里有一些关于在使用ShaderMaterial
时默认使用哪些制服、属性和命名约定的详细信息。
您想要应用于整个场景的每个效果(后期处理)都应该传递给 EffectComposer。 这是文档: https://threejs.org/docs/#manual/en/introduction/How-to-use-post-processing 。
此外,有时您可以通过在渲染器元素上设置诸如模糊之类的 CSS 规则来应用一些效果,如下所示:
renderer.domElement.style.filter = `blur(10px)`;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.