three 中 InstancedInterleavedBuffer InterleavedBufferAttribute 使用小结

126 阅读2分钟

InstancedInterleavedBuffer 是什么有什么用

  • 与 InstancedBufferAttribute 一样用于多个几何体重复渲染的场景区别在于这个用于更复杂及性能优化的场景
  • 这个是与 InterleavedBufferAttribute 配合使用
  • 要注意的是第三个参数一般设置 为 1

InterleavedBufferAttribute 是什么有什么用

  • 与 InstancedInterleavedBuffer 配合使用,用来存储Buffer数据
  • 用于在几何体中 setAttribute 使用

InterleavedBuffer

  • InterleavedBufferAttribute 是从 这个API封装而来

基本使用示例


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


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();
    scene.background = new THREE.Color(0xeeeeee);
    const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 2000 );
    camera.position.set( 0, 300, 800 );
    camera.lookAt( 0, 0, 0 );


    const controls = new OrbitControls(camera, renderer.domElement);

    

        
    // 创建一个基本的立方体几何体
    const geometry = new THREE.BoxGeometry(1, 1, 1);

    // 定义实例化渲染的数量
    const instanceCount = 100;
    // 创建一个数组来存储每个实例的偏移量(位置)和颜色
    const instanceData = new Float32Array(instanceCount * 6); // 每个实例有3个位置和3个颜色属性


    for (let i = 0; i < instanceCount; i++) {
        const x = Math.random() * 400 - 200;
        const y = Math.random() * 400 - 200;
        const z = Math.random() * 400 - 200;

        instanceData[i * 6] = x;
        instanceData[i * 6 + 1] = y;
        instanceData[i * 6 + 2] = z;

        instanceData[i * 6 + 3] = Math.random();
        instanceData[i * 6 + 4] = Math.random();
        instanceData[i * 6 + 5] = Math.random();
    }

    // 创建 InstancedInterleavedBuffer
    const instancedBuffer = new THREE.InstancedInterleavedBuffer(instanceData, 6, 1);

    // 创建 InterleavedBufferAttribute,用于位置和颜色属性
    const positionAttribute = new THREE.InterleavedBufferAttribute(instancedBuffer, 3, 0);
    const colorAttribute = new THREE.InterleavedBufferAttribute(instancedBuffer, 3, 3);

    // 将这些属性添加到几何体中
    geometry.setAttribute('instancePosition', positionAttribute);
    geometry.setAttribute('instanceColor', colorAttribute);

    // 创建自定义着色器材质
    const material = new THREE.ShaderMaterial({
        vertexShader: `
            attribute vec3 instancePosition;
            attribute vec3 instanceColor;
            varying vec3 vColor;
            void main() {
                vColor = instanceColor;
                vec4 mvPosition = modelViewMatrix * vec4(position + instancePosition, 1.0);
                gl_Position = projectionMatrix * mvPosition;
            }
        `,
        fragmentShader: `
            varying vec3 vColor;
            void main() {
                gl_FragColor = vec4(vColor, 1.0);
            }
        `,
        side: THREE.DoubleSide
    });


    // 使用 InstancedMesh 来进行实例化渲染
    const mesh = new THREE.InstancedMesh(geometry, material, instanceCount);

    // 将网格添加到场景中
    scene.add(mesh);

    function animate() {
        requestAnimationFrame(animate);
        controls.update();
        renderer.render(scene, camera);
    }

    animate();

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

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

</style>