demo
const material = new THREE.ShaderMaterial({
vertexShader: `
varying vec2 vUv;
varying float vDist;
varying float vRandom;
uniform vec2 mouse;
uniform float radius;
uniform float time;
uniform float drag;
// 随机函数
float random(vec2 st) {
return fract(sin(dot(st.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
void main() {
vUv = uv;
vec3 pos = position;
// 基于位置和时间生成随机值
float rand = random(pos.xy) * 1.01 - 0.01;
vRandom = rand;
// 计算打散效果
float disperseFactor = sin(time * 0.5) * 0.00001;
vec3 disperseDir = vec3(
rand * disperseFactor,
rand * disperseFactor,
0
);
// 鼠标交互
vec2 mouseDir = pos.xy - mouse;
float dist = length(mouseDir);
if (dist < radius) {
float force = (radius - dist) / radius;
pos.xy += normalize(mouseDir) * force * 0.5;
}
// 应用打散效果
pos += disperseDir;
// 减小粒子大小
gl_PointSize = 3.0 * (1.0 + random(pos.xy));
vec4 mvPosition = modelViewMatrix * vec4(pos, 1.0);
gl_Position = projectionMatrix * mvPosition;
vDist = dist;
}`,
fragmentShader: `
uniform sampler2D mainTexture;
varying vec2 vUv;
varying float vDist;
varying float vRandom;
uniform float time;
// 颜色调整辅助函数
vec3 adjustColor(vec3 color) {
// 增加对比度
vec3 contrast = (color - 0.5) * 1.4 + 0.5;
// 计算亮度
float luminance = dot(contrast, vec3(0.299, 0.587, 0.114));
// 增加饱和度
vec3 saturated = mix(vec3(luminance), contrast, 1.3);
// 稍微压暗高光
saturated = pow(saturated, vec3(1.1));
return saturated;
}
void main() {
// 马赛克大小
float mosaicSize = 1000.0;
vec2 mosaicUv = floor(vUv * mosaicSize) / mosaicSize;
// 减小抖动效果
float jitter = sin(time * 2.0 + vRandom * 1.28) * 0.001;
mosaicUv += vec2(jitter);
vec4 texColor = texture2D(mainTexture, mosaicUv);
// 调整颜色
vec3 adjustedColor = adjustColor(texColor.rgb);
// 调整扭曲和淡出效果
float distortionFactor = 1.0 - vDist * 0.005;
float alpha = 0.99 + 0.01 * sin(time * 2.0 + vRandom * 6.28);
// 边缘淡出效果
float edgeFade = 1.0 - length(gl_PointCoord - vec2(0.5)) * 2.0;
edgeFade = smoothstep(0.0, 0.5, edgeFade);
gl_FragColor = vec4(adjustedColor, texColor.a * alpha * edgeFade);
}`,
uniforms: {
mainTexture: { value: texture.value },
mouse: { value: new THREE.Vector2(0, 0) },
radius: { value: 0.5 },
time: { value: 0 },
drag: { value: 0.98 },
},
transparent: true,
side: THREE.DoubleSide,
depthWrite: false,
blending: THREE.AdditiveBlending,
});