在之前文章基础上,修改实现光柱在两种颜色之间的平滑渐变效果

为了使之前文章的光柱实现渐变发光效果,我们可以利用 THREE.ShaderMaterial 来自定义材质,并通过时间动态改变材质的颜色属性。以下是如何修改和扩展上述代码以实现这一效果:

  1. 引入必要的模块:确保引入了 ShaderMaterialUniformsUtilsClock 等必要的模块。
  2. 定义自定义着色器:编写简单的 vertex 和 fragment 着色器来实现颜色的渐变效果。
  3. 使用 Clock 来获取时间:用时间来控制颜色的变化。
  4. 更新渲染函数:在渲染函数中更新着色器的统一变量。

下面是修改后的代码:

import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { Group, PlaneGeometry, TextureLoader, ShaderMaterial, UniformsUtils, Clock, Mesh, DoubleSide } from 'three';

export const Pillar = (config?: Partial<{
    width: number;
    height: number;
    lightPillarUrl: string;
    color1: number; // 起始颜色  
    color2: number; // 结束颜色  
    minScale: number;
    maxScale: number;
    scaleSpeed: number;
}>) => {
    const defaultConfig = {
        height: 20,
        lightPillarUrl: "./pillarTexture.png",
        color1: 0x00ffff,
        color2: 0xff00ff,
        minScale: 1,
        maxScale: 2,
        scaleSpeed: 0.01
    };

    const conf = {
        ...defaultConfig,
        ...config
    };

    const ratios = 255 / 41;
    const width = conf.height / ratios;
    const group = new Group();

    const geometry = new PlaneGeometry(width, conf.height);
    geometry.rotateX(Math.PI / 2);
    geometry.translate(0, 0, conf.height / 2);

    const textureLoader = new TextureLoader();
    const uniforms = UniformsUtils.merge([
        {
            u_time: { value: 1.0 },
            u_color1: { value: new THREE.Color(conf.color1) },
            u_color2: { value: new THREE.Color(conf.color2) },
            u_texture: { value: textureLoader.load(conf.lightPillarUrl) }
        }
    ]);

    const vertexShader = `  
        varying vec2 vUv;  
        void main() {  
            vUv = uv;  
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);  
        }  
    `;

    const fragmentShader = `  
        uniform sampler2D u_texture;  
        uniform float u_time;  
        uniform vec3 u_color1;  
        uniform vec3 u_color2;  
        varying vec2 vUv;  
  
        void main() {  
            float mixFactor = abs(sin(u_time));  
            vec3 color = mix(u_color1, u_color2, mixFactor);  
            vec4 textureColor = texture2D(u_texture, vUv);  
            gl_FragColor = vec4(color, textureColor.a);  
        }  
    `;

    const material = new ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vertexShader,
        fragmentShader: fragmentShader,
        transparent: true,
        depthWrite: false,
        side: DoubleSide
    });

    const mesh = new Mesh(geometry, material);
    const mesh2 = mesh.clone();
    mesh2.rotateZ(Math.PI / 2);

    group.add(mesh, mesh2);

    let currentScale = conf.minScale;
    let scalingUp = true;
    const clock = new Clock();

    const render = () => {
        const delta = clock.getDelta();

        if (scalingUp) {
            currentScale += conf.scaleSpeed;
            if (currentScale >= conf.maxScale) {
                scalingUp = false;
            }
        } else {
            currentScale -= conf.scaleSpeed;
            if (currentScale <= conf.minScale) {
                scalingUp = true;
            }
        }

        group.scale.set(currentScale, currentScale, currentScale);
        group.rotation.z += 0.01;

        // 更新时间  
        uniforms.u_time.value = clock.elapsedTime;
    };

    return { mesh: group, render };
};

说明:

  1. 着色器
    • vertexShader:传递 UV 坐标。
    • fragmentShader:使用时间来在两种颜色之间进行插值,并应用纹理。
  2. Clock
    • 使用 Clock 对象来获取运行的时间,用于控制颜色渐变。
  3. uniforms
    • 定义了一些统一变量,包括时间 u_time,起始颜色 u_color1,结束颜色 u_color2,以及纹理 u_texture
  4. 渲染函数
    • 在渲染函数中更新 u_time 统一变量,使得颜色能够随时间渐变。

通过这种方式,光柱将能够实现在两种颜色之间的平滑渐变效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值