我正在学习着色器,并且有一个正在构建的小项目。该项目基于将鼠标悬停在粒子上时将粒子转换为纹理。现在我有大约 85% 的逻辑下降,但我想要在鼠标悬停时进行更多的完整转换,但似乎无法正确处理。比如,当鼠标没有悬停在网格上时,我应该只看到网格,当它悬停在上面时,我应该看到 100% 的纹理和它的新位置。
我能够更新我原来的东西,它更接近我的视觉,但是当我刷新页面时,首先显示纹理而不是粒子。那就是我需要帮助弄清楚我需要修复的地方。
顶点着色器
varying vec2 vUv;
varying vec3 vPos;
varying vec2 vCoordinates;
attribute vec3 aCoordinates;
attribute vec3 aPosition;
uniform float uTime;
uniform vec2 uMouse;
uniform float uRadius;
mat3 rotation3dY(float angle) {
float s = sin(angle);
float c = cos(angle);
return mat3(c, 0.0, -s, 0.0, 1.0, 0.0, s, 0.0, c);
}
void main() {
vUv = uv;
// START
float distanceFactor = uRadius - distance(aPosition, vec3(0.0));
vec3 start = aPosition * rotation3dY(uTime * 0.2 * distanceFactor);
// TRANSITION
vec3 plane = position;
float moveDist = distance(start.xy, uMouse * 2.0);
float moveArea = smoothstep(0.0, 1024.0, moveDist);
vec3 finalPos = abs(moveDist/ 8.0) > 32.0 ? start : plane;
// END
vec4 mvPosition = modelViewMatrix * vec4(finalPos, 1.0);
vec4 viewPosition = viewMatrix * mvPosition;
gl_PointSize = 3000.0;
gl_PointSize *= (1.0 / -viewPosition.z);
gl_Position = projectionMatrix * mvPosition;
vCoordinates = aCoordinates.xy;
vPos = start;
}
片段
varying vec2 vCoordinates;
varying vec3 vPos;
uniform sampler2D ish;
uniform sampler2D mask;
uniform float uMove;
void main() {
vec4 maskTexture = texture2D(mask, gl_PointCoord);
vec2 myUV = vec2(vCoordinates.x / 512.0, vCoordinates.y / 512.0);
vec4 image = texture2D(ish, myUV);
float alpha = 1.0 - clamp(0.0, 1.0, abs(vPos.z / 900.0));
gl_FragColor = image;
gl_FragColor.a *= maskTexture.r * alpha;
}
相关Three.js代码
mouseEffects() {
this.test = new THREE.Mesh(
new THREE.PlaneGeometry(512, 512),
new THREE.MeshBasicMaterial()
)
window.addEventListener('mousemove', (evt) => {
this.move += evt.clientY / 100;
this.mouse.x = (evt.clientX / window.innerWidth) * 2 - 1;
this.mouse.y = -(evt.clientY / window.innerHeight) * 2 + 1;
this.raycaster.setFromCamera(this.mouse, this.camera);
let intersects = this.raycaster.intersectObjects([this.test]);
console.log(intersects[0].point);
this.point.x = intersects[0].point.x;
this.point.y = intersects[0].point.y;
}, false);
}
addMesh() {
const number = 512 * 512;
this.material = new THREE.ShaderMaterial({
vertexShader,
fragmentShader,
uniforms: {
progress: { type: "f", value: 0.0 },
ish: { type: "t", value: this.textures[0] },
logo: { type: "t", value: this.textures[1] },
mask: { type: "t", value: this.mask },
uMouse: { type: "v2", value: null },
uTime: { type: "f", value: 0.0 },
uRadius: {
type: "f", value: 2
}
},
side: THREE.DoubleSide,
depthTest: false,
depthWrite: false,
transparent: true,
})
this.geometry = new THREE.BufferGeometry();
this.positions = new THREE.BufferAttribute(new Float32Array(number * 3), 3);
this.startPos = new THREE.BufferAttribute(new Float32Array(number * 3), 3)
this.coordinates = new THREE.BufferAttribute(new Float32Array(number * 3), 3);
this.speeds = new THREE.BufferAttribute(new Float32Array(number), 1);
this.offset = new THREE.BufferAttribute(new Float32Array(number), 1);
this.directions = new THREE.BufferAttribute(new Float32Array(number), 1);
this.press = new THREE.BufferAttribute(new Float32Array(number), 1);
function rand(a, b) {
return a + (b - a) * Math.random();
}
let index = 0;
for (let i = 0; i < 512; i++) {
let posX = i - 256;
for (let j = 0; j < 512; j++) {
this.positions.setXYZ(index, posX * 2, (j - 256) * 2, 0);
this.coordinates.setXYZ(index, i, j, 0);
this.offset.setX(index, rand(-1000, 1000));
this.speeds.setX(index, rand(0.4, 1));
this.directions.setX(index, Math.random() > 0.5 ? 1 : -1);
this.press.setX(index, rand(0.4, 1));
const phi = Math.random() * Math.PI * 2;
let r = 0.2 + (Math.random() < 0.6 ? Math.pow(Math.random(), 1 / 6) + 0.001 : Math.pow((1 + 200 * Math.random()) * Math.random(), 3 / 6));
this.startPos.setXYZ(index, (r * 16) * Math.cos(phi), (r * 16) * Math.sin(phi), 0)
index++;
}
}
this.geometry.setAttribute("position", this.positions);
this.geometry.setAttribute("aPosition", this.startPos);
this.geometry.setAttribute("aCoordinates", this.coordinates);
this.geometry.setAttribute("aOffset", this.offset);
this.geometry.setAttribute("aSpeed", this.speeds);
this.geometry.setAttribute("aDirection", this.directions);
this.geometry.setAttribute("aPress", this.press);
this.mesh = new THREE.Points(this.geometry, this.material);
this.scene.add(this.mesh);
}