InstancedMesh(实例化网格)是Threejs提供的一种特殊的网格Mesh,它可以批量创建具有相同几何体和材质的物体;
构造函数
InstancedMesh( geometry : BufferGeometry, material : Material, count : Integer ) 要创建一个InstancedMesh,需要三个参数,几何体(BufferGeometry类型),材质(Material类型)和要创建的总数(Integer 类型)
属性
.count : Integer 实例的数量。被传入到构造函数中的count表示mesh实例数量的最大值。 可以在运行时改变这个数值到 [0, count] 区间的一个整数 .instanceColor : InstancedBufferAttribute 代表所有实例的颜色。默认情况下null。 如果通过.setColorAt()修改实例化数据,则必须将它的needsUpdate标志设置为 true .instanceMatrix : InstancedBufferAttribute 表示所有实例的本地变换。 如果你要通过 .setMatrixAt() 来修改实例数据,你必须将它的 needsUpdate 标识为 true .isInstancedMesh : Boolean 只读属性,判断一个对象是否是InstancedMesh类型
方法
.dispose () 释放实例的内部资源 .getColorAt ( index : Integer, color : Color ) 获取实例的颜色,它有两个参数, index:实例索引,取值范围为0~count color:已定义的颜色对象 .getMatrixAt ( index : Integer, matrix : Matrix4 ) 获得已定义实例的本地变换矩阵,它有两个参数 index: 实例的索引。值必须在 [0, count] 区间 matrix: 该4x4矩阵将会被设为已定义实例的本地变换矩阵 .setColorAt ( index : Integer, color : Color ) 将给定的颜色设置为定义的实例,它包含两个参数 index:实例索引,取值范围为0~count color:单个实例的颜色 这里需要注意 确保在使用setColorAt 更新所有颜色后将.instanceColor.needsUpdate设置为true .setMatrixAt ( index : Integer, matrix : Matrix4 ) 设置给定的本地变换矩阵到已定义的实例,需要两个参数 index: 实例的索引。值必须在 [0, count] 区间 matrix: 一个4x4矩阵,表示单个实例本地变换 这里需要注意 确保在使用setMatrixAt 更新所有矩阵后将 .instanceMatrix.needsUpdate 设置为true
InstancedMesh实例应用
使用InstancedMesh实现Threejs案例中的instancing / raycast 效果 引入Threejs并创建场景
代码语言:javascript复制import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
// 场景
const scene = new THREE.Scene()
scene.background = new THREE.Color(0x808080)
创建几何体 这里使用Threejs提供的IcosahedronGeometry来创建几何体 IcosahedronGeometry是二十面缓冲几何体,用于生成一个二十面体,其构造函数如下: IcosahedronGeometry(radius : Float, detail : Integer) 它包含两个参数 radius — 二十面体的半径,默认为1。 detail — 默认值为0。将这个值设为一个大于0的数将会为它增加一些顶点,使其不再是一个二十面体。当这个值大于1的时候,实际上它将变成一个球体
代码语言:javascript复制const geometry = new THREE.IcosahedronGeometry(0.5,5)
创建材质
代码语言:javascript复制const material = new THREE.MeshPhongMaterial({color:0xffffff})
创建物体 这里使用InstancedMesh来批量创建物体
代码语言:javascript复制let amount = 10
let count = Math.pow(amount,3) //amount 的三次方,1000个
const meshes = new THREE.InstancedMesh(geometry,material,count) //InstancedMesh 创建多个形状材质相同的物探,count 数量
循环设置meshes中每一个小球的位置和颜色 我们首先定义一个变量index作为每一个小球的索引ID,初始值为0 定义一个变量white,用于存放Threejs中的颜色 定义一个offset,用于存放偏移量,即两个小球之间的间隔 定义一个四维矩阵用于存放物体的位置 然后通过三层for循环遍历每一个小球,并设置其位置和颜色
代码语言:javascript复制// 定义每个小球的id索引,作为小球的标识
let index = 0
// 定义颜色
let white = new THREE.Color().setHex(0xffffff)
// 定义每个小球位置的偏移量
const offset = (amount -1 ) / 2 //4.5,即每个小球间隔4.5
// 转换矩阵,
const matrix = new THREE.Matrix4()
for(let i = 0 ; i < amount; i ) {
for(let j = 0; j < amount; j ) {
for(let k = 0; k < amount; k ) {
// 设置matrix的位置,根据偏移量
matrix.setPosition(offset - i, offset - j, offset - k) //-4.5 ~ 4.5
// 将index和matrix赋值给meshes
meshes.setMatrixAt(index,matrix)
// 设置每个小球的颜色
meshes.setColorAt(index,white)
index = index 1
}
}
}
scene.add(meshes)
创建光、辅助轴和相机
代码语言:javascript复制// 辅助轴
const axesHelper = new THREE.AxesHelper(50)
scene.add(axesHelper)
// 灯光
const light = new THREE.HemisphereLight(0xffffff,0x888888)
light.position.set(0,1,0)
scene.add(light)
// 相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,1,1000)
camera.position.set(20,20,20)
创建渲染器
代码语言:javascript复制// 渲染器
const renderer = new THREE.WebGLRenderer()
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth,window.innerHeight)
document.body.appendChild(renderer.domElement)
添加轨道控制器使用鼠标控制相机
代码语言:javascript复制const control = new OrbitControls(camera,renderer.domElement)
创建循环渲染函数并调用
代码语言:javascript复制function render() {
requestAnimationFrame(render)
renderer.render(scene,camera)
}
render()
刷新浏览器查看效果
可以通过随机函数使每个小球的颜色都随机显示不同的颜色 将上面定义的颜色变量white修改为如下代码,即可实现随机颜色效果
代码语言:javascript复制//let white = new THREE.Color().setHex(0xffffff)
let white = new THREE.Color().setHex(Math.random() * 0xffffff))
OK,今天就先到这里吧,下次我们来实现这个有小球组成的立方体与鼠标的交互效果,仿照Threejs案例中的效果来实现当鼠标滑过某个小球时,使某个小球变色的效果。喜欢的关注点赞收藏哦