提问人:haru 提问时间:10/21/2023 更新时间:10/21/2023 访问量:45
如何在 fragmentShader 中以 three.js 的形式保留值?
How do I retain values in fragmentShader in three.js?
问:
我想使用three.js ShaderMaterial将粒子动画应用于纹理。
粒子动画的细节
1:仅首次出现 fragmentShader 的行为 1_1:为每个像素分配一个随机坐标值 (参考:https://thebookofshaders.com/10/?lan=jp)
统一 int 标志;标志在三个.js渲染器中递增 1(初始值为 -1)
浮点随机(vec2 st) {
返回 fract( sin( dot(st.xy, vec2(12.9898, 78.233)) ) * 43758.5453123 );
}
如果(标志 == 0) {
vec2 移动 = 随机 (UV);
}
1_2:将 uv 坐标值分配给变量以保存纹理的原始坐标值
变化的 vec2 vUV;
vec2 uv = vUv;
如果(标志 == 0) {
VEC2 原点 = UV;
}
2:第二次后 fragmentShader 的行为 将每个粒子从 1_1 中分配的随机坐标值收敛到 1_2 中保留的原始坐标值
计算公式如下 (参考:https://www.youtube.com/watch?v=vAJEHf92tV0&list=WL&index=54&t=3934s)
float ease = 0.01;
move.x += (origin.x - move.x) * ease;
move.y += (origin.y - move.y) * ease;
但是,在上述 fragmentShader 的第二次之后, 在 main 函数之前声明它并使作用域全局不起作用,因为在声明变量时会重置该值。
我想知道如何在对 fragmentShader 的第二次和后续调用中引用 move 和 origin 的值。具体来说,我想知道如何保留这些值。先谢谢你。
-源代码-
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>nier three.js use case</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/0.157.0/three.min.js"></script>
<style>
body {
margin: 0;
overflow: hidden;
}
</style>
</head>
<body>
<div id="renderer"></div>
<script>
function init() {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 10;
const renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x4a1c1c);
const loader = new THREE.TextureLoader();
const texture = loader.load('./image.png');
const vertexShader = `
varying vec2 vUv;
varying vec3 pos;
void main() {
vUv = uv;
pos = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;
const fragmentShader = `
uniform sampler2D texture_;
varying vec2 vUv;
varying vec3 pos;
uniform float time;
uniform vec2 resolution;
uniform int flag;
float random(vec2 st) {
return fract( sin( dot(st.xy, vec2(12.9898, 78.233)) ) * 43758.5453123 );
}
void main() {
vec2 uv = vUv;
float ease = 0.01;
vec4 color;
vec2 st = gl_FragCoord.xy / resolution.xy;
vec2 origin = vec2(0, 0);
vec2 move = vec2(0, 0);
if (flag == 0) {
origin = uv;
move = vec2(random(st), random(st));
}
else {
move.x += (origin.x - move.x) * ease;
move.y += (origin.y - move.y) * ease;
}
color = texture(texture_, move);
gl_FragColor = color;
}
`;
const geometry = new THREE.PlaneGeometry(25, 15);
const material = new THREE.ShaderMaterial({
uniforms: {
texture_: { value: texture },
time: { value: 0.0 },
flag: { value: -1 },
resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
},
vertexShader: vertexShader,
fragmentShader: fragmentShader,
});
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(-2, 0, 0);
scene.add(mesh);
document.getElementById('renderer').appendChild(renderer.domElement);
render();
function render() {
requestAnimationFrame(render);
material.uniforms.time.value += 0.01;
material.uniforms.flag.value += 1;
renderer.render(scene, camera);
}
}
window.onload = init;
</script>
</body>
</html>
答: 暂无答案
评论