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();
}