WebGL模糊着色器中的三个JS



这是一个很长的机会,但我绝望地迷失了方向。我一段时间前就开始学习Three.JS,并想将我的项目从P5.JS迁移(作为一种练习,但有在未来使用它的想法(。在P5.js中,我只是制作了一个画布并应用了着色器,但在Three.js中,它似乎不起作用。所以我想了——我会在着色器中尝试一下。

想法:

  1. 绘制随机圆(在透明背景上(
  2. 模糊圆圈
  3. 将结果用作纹理

到目前为止,我已经成功地绘制了圆(还不是随机的,但仍在处理它(并将其用作纹理。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
});

Vert着色器部分:

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;
}`;

我的线路有问题CCD_ 1。我不知道如何在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-使用后处理
此外,有时您可以通过在渲染器元素上设置模糊等css规则来应用一些效果,如下所示:

renderer.domElement.style.filter = `blur(10px)`;

最新更新