请添加图片描述

在这里插入图片描述

一个模型
/*
 * @Author: hongbin
 * @Date: 2022-09-30 12:05:35
 * @LastEditors: hongbin
 * @LastEditTime: 2022-10-01 09:31:09
 * @Description:逐帧通过uniform改变模型颜色
 */
import * as THREE from "three";

export const ColorChangesConstantly = () => {
    const vertexShader = `
        varying vec2 vUv;
        varying vec3 vPosition;

        void main () {
            vUv = uv;
            vPosition = position;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
        }
    `;
    const fragmentShader = `
        varying vec2 vUv;
        varying vec3 vPosition;
        uniform float time;

        void main () {
            float r = sin(time);
            float g = vUv.y;
            float b = cos(sin(time));

            if(abs(vPosition.y) >= 3.0){
                g = vPosition.y > 0.0 ? 1.0 : 0.0;
            }

            gl_FragColor = vec4(r,g,b,1);
        }
    `;
    const clock = new THREE.Clock();

    const uniforms = {
        time: { value: clock.getElapsedTime() },
    };

    const tick = () => {
        requestAnimationFrame(tick);
        uniforms.time.value = clock.getElapsedTime();
        window.render();
    };

    tick();

    const box = new THREE.Mesh(
        new THREE.BoxGeometry(5, 6, 10),
        new THREE.ShaderMaterial({
            vertexShader,
            fragmentShader,
            uniforms,
        })
    );
    return box;
};

多个模型

多个模型就不能每一一个定时器了 颜色更改在一个定时器中执行 减小开销

/*
 * @Author: hongbin
 * @Date: 2022-09-30 12:05:35
 * @LastEditors: hongbin
 * @LastEditTime: 2022-10-01 12:10:45
 * @Description:逐帧通过uniform改变模型颜色
 */
import * as THREE from "three";
import { Material } from "three";

let x = 0;
let z = 0;

export const ColorChangesConstantlyGroup = (itemCount: number) => {
    const group = new THREE.Group();
    const clock = new THREE.Clock();

    for (let i = 0; i < itemCount; i++) {
        group.add(
            ColorChangesConstantly({
                width: 1 + Math.random() * 2,
                length: 2 + Math.random() * 10,
                depth: 1 + Math.random() * 2,
            })
        );
    }

    const tick = () => {
        requestAnimationFrame(tick);
        group.children.forEach((m: THREE.Object3D) => {
            //@ts-ignore
            m.material.uniforms.time.value = clock.getElapsedTime();
            // m.scale.y += 0.01;
            //@ts-ignore
            m.rotation.y += m.material.uniforms.random.value / 10;
        });
        window.render();
    };

    tick();

    return group;
};

export const ColorChangesConstantly = ({
    width,
    length,
    depth,
}: {
    width: number;
    length: number;
    depth: number;
}) => {
    const vertexShader = `
        varying vec2 vUv;
        varying vec3 vPosition;
        uniform float time;
        vec3 TempPosition;

        void main () {
            vUv = uv;
            vPosition = position;
            TempPosition = position;
            gl_Position = projectionMatrix * modelViewMatrix * vec4(TempPosition,1.0);
        }
    `;
    const fragmentShader = `
        varying vec2 vUv;
        varying vec3 vPosition;
        uniform float time;
        uniform float maxY;
        uniform float random;

        void main () {
            float r = sin(time);
            float g = vUv.y;
            float b = cos(sin(time)) * random;

            if(abs(vPosition.y) >= maxY){
                g = vPosition.y > 0.0 ? 1.0 : 0.0;
            }

            gl_FragColor = vec4(r,g,b,1);
        }
    `;

    const uniforms = {
        time: { value: 0 },
        maxY: { value: length / 2 },
        random: { value: Math.random() },
    };

    const box = new THREE.Mesh(
        new THREE.BoxGeometry(width, length, depth),
        new THREE.ShaderMaterial({
            vertexShader,
            fragmentShader,
            uniforms,
        })
    );
    box.position.y += length / 2;
    box.position.x = x;
    box.position.z = z + Math.random() * 5;
    x += width * 3;
    if (x > 160) {
        x = 0;
        z += 10;
    }

    box.userData.setY = (num: number) => {
        box.position.y += num;
        return box;
    };

    return box;
};

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐