webgl instance 绘制
效果:
key1: 创建实例缓存
function createMesh() {for (let i = 0; i < NUM_CUBE; i++) {const angle = i * 2 * Math.PI / NUM_CUBE;const x = Math.sin(angle) * RADIUS;const y = 0;const z = Math.cos(angle) * RADIUS;cubes[i] = {scale: new THREE.Vector3(0.5, 0.5, 0.5),position: new THREE.Vector3(x, y, z),modelMatrix: new THREE.Matrix4(),rotation: new THREE.Euler(0, 0, 0),quaternion: new THREE.Quaternion(),};}// key1: 创建实例缓存modelMatrixData = new Float32Array(NUM_CUBE * 16);modelMatrixBuffer = WebGLVertex.createMatrix4x4(gl, {location: 3,data: modelMatrixData,});
}
key2: 在创建vao之后创建 实例缓存
// key2: 在创建vao之后创建 实例缓存
const geometry = getCubeGeometry(gl, createMesh)
/*** @export* @param {*} gl* @param {*} unbindVaoBefor 解绑vao之前的回调函数*/
export function getCubeGeometry(gl, unbindVaoBefor) {const { attributes, index } = new THREE.BoxGeometry();const vao = gl.createVertexArray();gl.bindVertexArray(vao);WebGLVertex.createBuffer(gl, {data: attributes.position.array});WebGLVertex.configureAttribute(gl, {location: 0,count: attributes.position.itemSize,type: gl.FLOAT,stride: 0,offset: 0,});WebGLVertex.createBuffer(gl, {data: attributes.uv.array});WebGLVertex.configureAttribute(gl, {location: 1,count: attributes.uv.itemSize,type: gl.FLOAT,stride: 0,offset: 0,});WebGLVertex.createBuffer(gl, {data: attributes.normal.array});WebGLVertex.configureAttribute(gl, {location: 2,count: attributes.normal.itemSize,type: gl.FLOAT,stride: 0,offset: 0,});WebGLVertex.createBuffer(gl, {glBufferType: gl.ELEMENT_ARRAY_BUFFER,data: index.array});unbindVaoBefor && unbindVaoBefor();gl.bindVertexArray(null);return {vao,attributes,indexed: true,index: index.array};
}
key3: 指定实例数量
const { program, uniforms } = WebGLProgram.buildPrograms(gl, shaders).cube;
cubeCommand = new DrawCommand({gl,camera,geometry: new Geometry(geometry),program: program,uniforms: uniforms,// key3: 指定实例数量instanceCount: cubes.length,renderState: new RenderState({depthTest: {enabled: true,}}),uniformsData: {uTexture: {type: "t",value: sphereTexture},}
})
key4: 更新矩阵
function updateMesh() {for (let i = 0; i < cubes.length; ++i) {cubes[i].rotation.x += i * 0.01 * Math.random();cubes[i].rotation.y += i * 0.01 * Math.random();cubes[i].rotation.z += i * 0.01 * Math.random();cubes[i].quaternion.setFromEuler(cubes[i].rotation, false);cubes[i].modelMatrix.compose(cubes[i].position, cubes[i].quaternion, cubes[i].scale);// key4: 更新矩阵modelMatrixData.set(cubes[i].modelMatrix.elements, i * 16);WebGLVertex.updateBuffer(gl, {buffer: modelMatrixBuffer,data: modelMatrixData,})}
}
循环渲染
function render() {updateCamera()updateMesh();gl.clearColor(0, 0, 0, 0);gl.clear(gl.COLOR_BUFFER_BIT);gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);gl.useProgram(program);cubeCommand.execute();
}