shader
logo.png
constructor(container) {
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
container.appendChild(renderer.domElement);
this.renderer = renderer;
this.clock = new THREE.Clock()
const map = new THREE.TextureLoader().load('logo.png')
map.wrapS = THREE.RepeatWrapping; // 允许纹理在x轴上阵列
this.uniforms = {
uTexture: {
value: map
},
uTime: {
value: 0
},
uMouse: {
value: [0, 0]
},
uSpeed: {
value: 0
}
}
let current = {
oldX: 0,
x: 0,
}
this.current = current;
this.isMoving = false
container.addEventListener('mousemove', (e) => {
const x = e.clientX / container.offsetWidth - 0.5
current.x = this.step(current.x, x, .2);
current.oldX = this.step(current.oldX, x, .05);
this.isMoving = true
})
this.fsQuad = new FullScreenQuad(
new THREE.RawShaderMaterial({
name: "raw",
uniforms: this.uniforms,
vertexShader: `
precision highp float;
precision highp int;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 mapTransform;
attribute vec3 position;
attribute vec2 uv;
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
`,
fragmentShader: `
precision highp float;
precision highp int;
varying vec2 vUv;
uniform float uTime;
uniform float uSpeed;
uniform vec2 uMouse;
uniform sampler2D uTexture;
void main() {
// 获取片段的纹理坐标
vec2 uv = vUv;
// 计算扭曲效果
float dist = smoothstep(-.1, uv.x, uv.x-.1) * mix(1., .9, smoothstep(.9, 1.1, uv.x));
// 计算鼠标移动效果
float m = smoothstep(0.4, 0.5, vUv.x-uMouse.x)-smoothstep(0.5, .6, vUv.x-uMouse.x);
// 对纹理坐标进行扭曲
uv.x *= dist;
uv.x += 0.02;
uv.x -= 1.5;
uv.x *= 1. + (m * .15 * uSpeed);
uv.x += 1.5;
// 计算色彩的色差效果
float aberration = 0.05 * uSpeed * m * sin(uv.y * 10. + uTime * 10.);
// 纹理采样并应用色差
float r = 1. - texture2D(uTexture, uv + vec2(uTime * 0.075 - aberration, -aberration)).r;
float g = 1. - texture2D(uTexture, uv + vec2(uTime * 0.075, 0.)).g;
float b = 1. - texture2D(uTexture, uv + vec2(uTime * 0.075 + aberration, aberration)).b;
// 将颜色限制在一定范围内
vec3 col = clamp(vec3(r, g, b), .0588, 1.);
// 设置片段的最终颜色
gl_FragColor = vec4(col, 1.);
}
`
})
);
this.animate = this.animate.bind(this);
this.animate();
}
step(currentValue, targetValue, rate) {
return currentValue + (targetValue - currentValue) * rate;
}
animate() {
if (this.isMoving) {
this.isMoving = false
this.uniforms.uSpeed.value = this.current.x - this.current.oldX
this.uniforms.uMouse.value = [this.current.x, 0]
} else {
this.uniforms.uSpeed.value = this.step(this.uniforms.uSpeed.value, 0, 0.05)
}
this.uniforms.uTime.value += this.clock.getDelta();
this.fsQuad.render(this.renderer)
requestAnimationFrame(this.animate);
}