Threejs + Shader 字体扭曲效果

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

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Three.js is a JavaScript library used for creating 3D graphics in the browser. It provides a set of built-in shaders that can be used to create various visual effects like reflections, refractions, shadows, and more. Three.js shaders are written in GLSL (OpenGL Shading Language), a C-like language used for programming graphics processing units (GPUs). To create a custom shader in Three.js, you need to define a new shader material and pass in the GLSL code as a string. Here is an example of a simple custom shader that applies a color gradient based on the object's Y position: ``` var customShader = new THREE.ShaderMaterial({ uniforms: { color1: { value: new THREE.Color(0xff0000) }, color2: { value: new THREE.Color(0x0000ff) } }, vertexShader: ` varying vec3 vPosition; void main() { vPosition = position; gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); } `, fragmentShader: ` uniform vec3 color1; uniform vec3 color2; varying vec3 vPosition; void main() { float t = (vPosition.y + 1.0) / 2.0; gl_FragColor = vec4(mix(color1, color2, t), 1.0); } ` }); var cube = new THREE.Mesh( new THREE.BoxGeometry(1, 1, 1), customShader ); scene.add(cube); ``` This shader defines two uniforms (color1 and color2) that represent the two colors of the gradient. In the vertex shader, we pass the vertex position to the fragment shader via a varying variable. In the fragment shader, we calculate the gradient value (t) based on the Y position of the vertex and use the mix() function to interpolate between the two colors. Finally, we set the output color using gl_FragColor.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山楂树の

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值