three.js Uniform 使用小结

117 阅读1分钟

Uniform 是什么有什么作用

  • Uniform 是一个与 GLSL 搭配着使用的 API
  • 这个API 使得 GLSL 中原本定死的渲染字符串有了动态的功能
  • 是与 ShaderMaterial 搭配着使用

使用示例


<template>
    <div id="parkingLot" ref="parkingLot">
    </div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import * as THREE from 'three';
const parkingLot = ref();


onMounted(() => {
    const DOMEl = parkingLot.value;
    // 获取 DOMEl 的宽度和高度,以设置渲染器的大小。
    const width = DOMEl.clientWidth;
    const height = DOMEl.clientHeight;


    const renderer = new THREE.WebGLRenderer();
    renderer.setSize( width, height );
    DOMEl.appendChild( renderer.domElement );
    const scene = new THREE.Scene();
    const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 2000 );
    camera.position.set( 0, 10, 100 );
    camera.lookAt( 0, 0, 0 );

    
    // 创建几何体
    const geometry = new THREE.PlaneGeometry(2, 2);

    // 创建 Uniform
    const uniforms = {
      u_Color: new THREE.Uniform(new THREE.Color(1.0, 0.0, 0.0)) // 初始颜色为红色
    };


    // 创建 ShaderMaterial
    const material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: `
        void main() {
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
      `,
      fragmentShader: `
        uniform vec3 u_Color;
        void main() {
          gl_FragColor = vec4(u_Color, 1.0);
        }
      `,
    });
    
    // 创建光源
    const light = new THREE.DirectionalLight(0x0000ff, 10);
    light.position.set(10, 10, 10);
    light.castShadow = true;
    scene.add(light);

    // 创建网格并添加到场景
    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);


    // 渲染循环,动态更新颜色
    function animate() {
      requestAnimationFrame(animate);

      // 动态计算颜色值
      const time = Date.now() * 0.001; // 时间(秒)
      const r = Math.sin(time) * 0.5 + 0.5; // 红色通道
      const g = Math.sin(time + Math.PI / 3) * 0.5 + 0.5; // 绿色通道
      const b = Math.sin(time + 2 * Math.PI / 3) * 0.5 + 0.5; // 蓝色通道

      // 更新颜色 Uniform
      uniforms.u_Color.value.set(r, g, b);

      renderer.render(scene, camera);
    }
    animate();

});
</script>
<style lang="scss" scoped="scoped">

    #parkingLot {
        width: 940px;
        height: 940px;
        border: 1px solid #ccc;
        margin: 30px auto;
    }

</style>