gpt4 book ai didi

webgl2 - 如何使用统一缓冲区对象和实例化渲染来绘制多个对象?

转载 作者:行者123 更新时间:2023-12-02 19:49:13 26 4
gpt4 key购买 nike

我想通过使用统一缓冲区对象和实例渲染来绘制带有动画的多个对象..

我已经用 for 循环实现了这一点,但我想一次性渲染它们。

这是我的代码,当单击鼠标时使用 for 循环渲染多个对象..

我正在使用四个外部库,分别是 webgl-utils.js、webgl-debug.js、cuon-utils.js、cuon-matrix.js。这些可以找到here .

"use strict";
const loc_aPosition = 1;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
uniform mat4 uRotMatrix;
uniform mat4 uScaleMatrix;
uniform vec2 uOffSet;
void main() {
gl_Position = aPosition * uScaleMatrix * uRotMatrix + vec4(uOffSet, 0, 0);
}`;

const FSHADER_SOURCE =
`#version 300 es
precision mediump float;
out vec4 fColor;
uniform vec4 uColor;
void main() {
fColor = uColor;
}`;


function main() {
// Retrieve <canvas> element
let canvas = document.getElementById('webgl');

// Get the rendering context for WebGL
let gl = canvas.getContext("webgl2");
if (!gl)
{
console.log('Failed to get the rendering context for WebGL');
return;
}

// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
{
console.log('Failed to intialize shaders.');
return;
}

const loc_uOffSet = gl.getUniformLocation(gl.program, 'uOffSet');
const loc_uColor = gl.getUniformLocation(gl.program, 'uColor');
const loc_uRotMatrix = gl.getUniformLocation(gl.program, 'uRotMatrix');
const loc_uScaleMatrix = gl.getUniformLocation(gl.program, 'uScaleMatrix');

if(!loc_uOffSet)
{
console.log("Failed to load uOffSet uniform variable.");
return;
}

if(!loc_uColor)
{
console.log("Failed to load uColor uniform variable.");
return;
}

if(!loc_uRotMatrix)
{
console.log("Failed to load uModelMatrix uniform variable.");
return;
}

if(!loc_uScaleMatrix)
{
console.log("Falied to load uScaleMatrix uniform variable.");
return;
}




let n = initVertexBuffers(gl);

if(n < 0)
{
console.log('Failed to set the positions of the vertices');
return;
}


// Register function (event handler) to be called on a mouse press

canvas.onmousedown = function(ev){ click(ev, gl, canvas) };

// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);

// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);


let tick = function()
{
animate(); // Update the rotation angle
draw(gl, loc_uRotMatrix, loc_uOffSet, loc_uColor, loc_uScaleMatrix); // Draw
requestAnimationFrame(tick, canvas); // Request that the browser calls tick
};
tick();
}


//These are the arrays for the attributes of the stars
let g_vertices = [];
let g_angles = [];
let g_colors = [];
let g_ages = [];
let g_scale = [];

const ANGLE_STEP = -60;


let g_last = Date.now();


function click(ev, gl, canvas)
{
let x = ev.clientX; // x coordinate of a mouse pointer
let y = ev.clientY; // y coordinate of a mouse pointer
let rect = ev.target.getBoundingClientRect();

x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);
y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);


// Store the coordinates and color
g_vertices.push([x,y]);
g_angles.push(0);
g_ages.push(Date.now());
g_scale.push(1);

let randomPos = Math.floor(Math.random() * Math.floor(3));
let rgba = [4];
let randomColor = Math.random();

for(let i = 0; i<4; i++)
{
rgba[i] = randomColor;
}

rgba[3] = 1.0;
rgba[randomPos] = Math.random();

g_colors.push(rgba);
}


//Make the BO for making stars
function initVertexBuffers(gl)
{

let vertices = new Float32Array([
0, -0.2,
-0.3, -0.4,
0.0, 0.5,
0.3, -0.4,
0.0, 0.5,
0.0, 0.3,
-0.4, 0.3,
0.4, 0.3,
0.0, 0.3,
]);
let n = 9;

//Create a buffer Object
let posBuffer = gl.createBuffer();

if(!posBuffer)
{
console.log('Failed to create the buffer object');
return;
}

//Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
//Write date into the buffer object
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

//Connect the assignment to a_Position variable
gl.vertexAttribPointer(loc_aPosition, 2, gl.FLOAT, false, 0, 0);

//Enable the assignment to a_Position variable
gl.enableVertexAttribArray(loc_aPosition);

return n;
}

function animate()
{
// Calculate the elapsed time
let now = Date.now();
let elapsed = now - g_last;
g_last = now;
// Update the current rotation angle (adjusted by the elapsed time)
for(let i = 0; i<g_angles.length; i++)
{
g_angles[i] = g_angles[i] + (ANGLE_STEP * elapsed) / 1000.0;
g_angles[i] %= 360;
g_scale[i] *= 0.99;
}
}


function draw(gl, loc_uModelMatrix, loc_uOffSet, loc_uColor, loc_uScaleMatrix)
{
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
let rotMatrix = new Matrix4();
let scaleMatrix = new Matrix4();

// Draw the stars
let len = g_vertices.length;
for(let i = 0; i < len; i++)
{
if((Date.now() - g_ages[i]) / 1000 > 3.5 ) // dissapear stars about 3.5 seconds after
continue;


let rgba = g_colors[i];
rotMatrix.setRotate(g_angles[i], 0, 0, 1);
scaleMatrix.setScale(g_scale[i], g_scale[i], 1);


//Set the uniform variables
gl.uniformMatrix4fv(loc_uModelMatrix, false, rotMatrix.elements);
gl.uniformMatrix4fv(loc_uScaleMatrix, false, scaleMatrix.elements);
gl.uniform2f(loc_uOffSet, g_vertices[i][0], g_vertices[i][1]);
gl.uniform4f(loc_uColor, rgba[0], rgba[1], rgba[2], rgba[3]);


gl.drawArrays(gl.TRIANGLE_FAN, 0, 9);


//Reset matrices for the next star
rotMatrix.setIdentity();
scaleMatrix.setIdentity();
}
}

这是示例图像,它的外观和工作原理:

enter image description here

我这样修改了上面的代码

"use strict";
const loc_aPosition = 1;
const VSHADER_SOURCE =
`#version 300 es
layout(location=${loc_aPosition}) in vec4 aPosition;
uniform matrices
{
mat4 uScaleMat;
mat4 uRotMat;
vec2 uOffSetXY;
};
void main() {
gl_Position = aPosition * uScaleMat * uRotMat + vec4(uOffSetXY, 0, 0);
}`;

// Fragment shader program
const FSHADER_SOURCE =
`#version 300 es
uniform colors
{
vec4 uColorVec;
}
precision mediump float;
out vec4 fColor;
void main() {
fColor = uColorVec;
}`;


function main() {
// Retrieve <canvas> element
var canvas = document.getElementById('webgl');

// Get the rendering context for WebGL
var gl = canvas.getContext("webgl2");
if (!gl)
{
console.log('Failed to get the rendering context for WebGL');
return;
}

// Initialize shaders
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
{
console.log('Failed to intialize shaders.');
return;
}

const loc_uOffSet = gl.getUniformLocation(gl.program, 'uOffSet');
const loc_uColor = gl.getUniformLocation(gl.program, 'uColor');
const loc_uModelMatrix = gl.getUniformLocation(gl.program, 'uModelMatrix');
const loc_uScaleMatrix = gl.getUniformLocation(gl.program, 'uScaleMatrix');

if(!loc_uOffSet)
{
console.log("Failed to load uOffSet uniform variable.");
return;
}

if(!loc_uColor)
{
console.log("Failed to load uColor uniform variable.");
return;
}

if(!loc_uModelMatrix)
{
console.log("Failed to load uModelMatrix uniform variable.");
return;
}

if(!loc_uScaleMatrix)
{
console.log("Falied to load uScaleMatrix uniform variable.");
return;
}



let matR = new Matrix4();
let matS = new Matrix4();
let offSetXY = [];
let colors = [];
let prog = gl.program
let {vao, n} = initVertexBuffers(gl);
let {vubo, cubo, matBuffer, colorBuffer} = initUBO(gl, prog, matR, matS, offSetXY, colors);

if(n < 0)
{
console.log('Failed to set the positions of the vertices');
return;
}


// Register function (event handler) to be called on a mouse press

canvas.onmousedown = function(ev){ click(ev, gl, canvas) };

// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);

// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);


let tick = function()
{
animate();
render(gl, prog, vao, n, g_stars, matBuffer, colorBuffer, matR, matS, offSetXY, colors, vubo, cubo)
requestAnimationFrame(tick, canvas); // Request that the browser calls tick
};
tick();
}


let g_vertices = []; // The array for the position of Triangle with mouse click
let g_angles = [];
let g_colors = [];
let g_ages = [];
let g_scale = [];
const ANGLE_STEP = -60;
const MAX_TRIANGLES = 30;
let g_last = Date.now();
let g_stars = 0;

function click(ev, gl, canvas)
{
let x = ev.clientX; // x coordinate of a mouse pointer
let y = ev.clientY; // y coordinate of a mouse pointer
let rect = ev.target.getBoundingClientRect();

x = ((x - rect.left) - canvas.width/2)/(canvas.width/2);
y = (canvas.height/2 - (y - rect.top))/(canvas.height/2);


// Store the coordinates and color
g_vertices.push([x,y]);
g_angles.push(0);
g_ages.push(Date.now());
g_scale.push(1);
g_stars++;

let randomPos = Math.floor(Math.random() * Math.floor(3));
let rgba = [4];
let randomColor = Math.random();

for(let i = 0; i<4; i++)
{
rgba[i] = randomColor;
}

rgba[3] = 1.0;
rgba[randomPos] = Math.random();

g_colors.push(rgba);
}


function initVertexBuffers(gl)
{

let vertices = new Float32Array([
0, -0.2,
-0.3, -0.4,
0.0, 0.5,
0.3, -0.4,
0.0, 0.5,
0.0, 0.3,
-0.4, 0.3,
0.4, 0.3,
0.0, 0.3,
]);
let n = 9;

//Create a buffer Object
let posBuffer = gl.createBuffer();
let vao = gl.createVertexArray();


if(!posBuffer)
{
console.log('Failed to create the buffer object');
return;
}

gl.bindVertexArray(vao);

//Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
//Write date into the buffer object
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

//Connect the assignment to a_Position variable
gl.vertexAttribPointer(loc_aPosition, 2, gl.FLOAT, false, 0, 0);

//Enable the assignment to a_Position variable
gl.enableVertexAttribArray(loc_aPosition);

return {vao, n};
}

function animate()
{
// Calculate the elapsed time
let now = Date.now();
let elapsed = now - g_last;
g_last = now;
// Update the current rotation angle (adjusted by the elapsed time)
for(let i = 0; i<g_angles.length; i++)
{
g_angles[i] = g_angles[i] + (ANGLE_STEP * elapsed) / 1000.0;
g_angles[i] %= 360;
g_scale[i] *= 0.99;
}
}


function draw(gl, loc_uModelMatrix, loc_uOffSet, loc_uColor, loc_uScaleMatrix)
{
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
let rotMatrix = new Matrix4();
let scaleMatrix = new Matrix4();

// Draw the rectangle
let len = g_vertices.length;
for(let i = 0; i < len; i++)
{
if((Date.now() - g_ages[i]) / 1000 > 3.5 )
continue;
let rgba = g_colors[i];

rotMatrix.setRotate(g_angles[i], 0, 0, 1);
scaleMatrix.setScale(g_scale[i], g_scale[i], 1);

gl.uniformMatrix4fv(loc_uModelMatrix, false, rotMatrix.elements);
gl.uniformMatrix4fv(loc_uScaleMatrix, false, scaleMatrix.elements);
gl.uniform2f(loc_uOffSet, g_vertices[i][0], g_vertices[i][1]);
gl.uniform4f(loc_uColor, rgba[0], rgba[1], rgba[2], rgba[3]);

gl.drawArrays(gl.TRIANGLE_FAN, 0, 9);


rotMatrix.setIdentity();
scaleMatrix.setIdentity();
}
}

function initUBO(gl, prog, matR, matS, offSetXY, colors)
{
let vertexBinding_Matrices = 1;
let fragBinding_Colors = 2;

let vubo = gl.createBuffer();
let cubo = gl.createBuffer();
gl.bindBufferBase(gl.UNIFORM_BUFFER, vertexBinding_Matrices, vubo);
gl.bindBufferBase(gl.UNIFORM_BUFFER, fragBinding_Colors, cubo);

let idx_uniform_block1 = gl.getUniformBlockIndex(prog, 'matrices');
let idx_uniform_block2 = gl.getUniformBlockIndex(prog, 'colors');

gl.uniformBlockBinding(prog, idx_uniform_block1, vertexBinding_Matrices);
gl.uniformBlockBinding(prog, idx_uniform_block2, fragBinding_Colors);

let FSIZE = 4;

let matBuffer = new ArrayBuffer(FSIZE * 16 * 2 + FSIZE * 2);

matR.elements = new Float32Array(matBuffer, 0, 16);
matS.elements = new Float32Array(matBuffer, FSIZE * 16, 16);
offSetXY = new Float32Array(matBuffer, FSIZE * 16 * 2, 2);

gl.bindBuffer(gl.UNIFORM_BUFFER, vubo);
gl.bufferData(gl.UNIFORM_BUFFER, FSIZE * 16 * 2 + FSIZE * 2, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);


let colorBuffer = new ArrayBuffer(FSIZE * 4);

colors = new Float32Array(colorBuffer, 0, 4);

gl.bindBuffer(gl.UNIFORM_BUFFER, cubo);
gl.bufferData(gl.UNIFORM_BUFFER, FSIZE * 4, gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.UNIFORM_BUFFER, null);


return {vubo, cubo, matBuffer, colorBuffer};
}


function render(gl, prog, vao, n, g_stars, matBuffer, colorBuffer, matR, matS, offSetXY, colors, vubo, cubo)
{

}

仍然有很多事情可以解决这个问题...我只是想知道我是否走在正确的轨道上...

是否有使用 ubos 和实例渲染的示例?

p.s由于我的母语不是英语,所以这个问题和代码可能都存在拼写错误...

最佳答案

统一缓冲区对象只是设置统一的一种不同方式。它们对实例化没有帮助。它们只是一种“可能”比使用gl.uniformXXX更快地设置制服的方法。例如,如果您有一个将环境光、漫反射、镜面反射、光泽度作为输入的着色器,您可以创建包含这 4 件制服的制服 block 。然后,您可以为每种 Material 创建一个统一的缓冲区对象,所有 4 个设置,您可以使用一个 WebGL 函数设置不同的 Material

gl.bindBufferRange(gl.UNIFORM_BUFFER, blockIndex, materialBuffer, [offset], [length]);

而不是 4 个 WebGL 调用

gl.uniform3fv(ambientLocation, ...);
gl.uniform3fv(diffuseLocation, ...);
gl.uniform3fv(specularLocation, ...);
gl.uniform1f(shininessLocation, ...);

因此,统一缓冲区对象对实例化没有帮助。他们所做的只是帮助更快地设置 uinform。我说“可能”是因为虽然我怀疑执行上述操作,但在初始化时预先创建一个统一缓冲区对象并在渲染时将其绑定(bind)到统一 block 肯定比调用 gl.uniform 4 倍要快。另一方面,如果制服的值每帧都发生变化,那么您需要通过使用新值调用 gl.bufferSubData 来更新缓冲区。这可能比调用 gl.uniform 快,也可能不快。我还没有介绍过它。 WebGL 的开销比 OpenGL 更多。你拥有的制服越多,速度可能会更快。

This answer显示了使用统一缓冲区对象的示例。

无论如何,重要的一点是它们只是一种更快的设置制服的方法。它们不启用新功能。

实例化绘图确实提供了新功能。能够通过 1 次绘制调用绘制多个事物,并且某些属性仅在每个实例更新一次,而不是像通常那样每个顶点更新一次。

因此,为了使用实例化绘图,您通常必须设置一些属性,其中的数据每个实例都会更改一次。最明显的是一个 mat4 属性,用于为每个实例提供不同的矩阵。当然,如果您希望每个实例有不同的颜色,您还需要提供颜色属性。

您只想每个实例更改一次的任何属性,而不是像平常调用的那样每个顶点更改一次

  gl.vertexAttribDivisor(attributeLocation, 1);

上面语句中的 1 表示仅每 1 个实例将属性前进到下一个值。在那里放 2 意味着该属性仅在 2 个实例后前进,等等。0 = 执行正常操作并前进每个顶点。

示例:

const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) alert('need WebGL2');

const positionLoc = 0;
const matrixLoc = 1; // note: mat4 attributes take 4 indices
const colorLoc = 5;


const vs = `#version 300 es
layout(location = ${positionLoc}) in vec4 position;

layout(location = ${matrixLoc}) in mat4 modelMatrix; // we'll make this per instance
layout(location = ${colorLoc}) in vec4 color; // we'll make this per instance

uniform mat4 viewProjection;

out vec4 v_color;

void main () {
gl_Position = viewProjection * modelMatrix * position;
v_color = color;
}
`;

const fs = `#version 300 es
precision mediump float;
in vec4 v_color;
out vec4 outColor;
void main() {
outColor = v_color;
}
`;

const program = twgl.createProgram(gl, [vs, fs]);
const viewProjectionLoc = gl.getUniformLocation(program, 'viewProjection');

const vao = gl.createVertexArray();
gl.bindVertexArray(vao);

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0, 0.2,
-0.2, -0.2,
0.2, -0.2,
]), gl.STATIC_DRAW);

gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);

const deg = v => v * Math.PI / 180;

// setup matrixes, one per instance
const matrixBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, matrixBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
...m4.rotateZ(m4.translation([-0.5, 0, 0]), deg(10)),
...m4.rotateZ(m4.translation([-0.25, 0, 0]), deg(20)),
...m4.rotateZ(m4.translation([0, 0, 0]), deg(30)),
...m4.rotateZ(m4.translation([0.25, 0, 0]), deg(40)),
...m4.rotateZ(m4.translation([0.5, 0, 0]), deg(50)),
]), gl.DYNAMIC_DRAW);

// set all 4 attributes for matrix
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(matrixLoc + i);
// note the stride and offset
gl.vertexAttribPointer(matrixLoc + i, 4, gl.FLOAT, false, 64, i * 16);
// this line says this attribute only changes for each 1 instance
gl.vertexAttribDivisor(matrixLoc + i, 1);
}

// setup colors, one per instance
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
1, 0, 1, 1,
0, 1, 1, 1,
]), gl.DYNAMIC_DRAW);

// set all attribute for color
gl.enableVertexAttribArray(colorLoc);
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
// this line says this attribute only changes for each 1 instance
gl.vertexAttribDivisor(colorLoc, 1);

gl.useProgram(program);
gl.uniformMatrix4fv(viewProjectionLoc, false, m4.identity());
gl.drawArraysInstanced(
gl.TRIANGLES,
0, // offset
3, // num vertices per instance
5, // num instances
);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>

要为它们设置动画,您需要通过调用 gl.bufferSubData 更新每帧 matrixBuffer 的缓冲区数据

const m4 = twgl.m4;
const gl = document.querySelector('canvas').getContext('webgl2');
if (!gl) alert('need WebGL2');

const positionLoc = 0;
const matrixLoc = 1; // note: mat4 attributes take 4 indices
const colorLoc = 5;


const vs = `#version 300 es
layout(location = ${positionLoc}) in vec4 position;

layout(location = ${matrixLoc}) in mat4 modelMatrix; // we'll make this per instance
layout(location = ${colorLoc}) in vec4 color; // we'll make this per instance

uniform mat4 viewProjection;

out vec4 v_color;

void main () {
gl_Position = viewProjection * modelMatrix * position;
v_color = color;
}
`;

const fs = `#version 300 es
precision mediump float;
in vec4 v_color;
out vec4 outColor;
void main() {
outColor = v_color;
}
`;

const program = twgl.createProgram(gl, [vs, fs]);
const viewProjectionLoc = gl.getUniformLocation(program, 'viewProjection');

const vao = gl.createVertexArray();
gl.bindVertexArray(vao);

const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
0, 0.2,
-0.2, -0.2,
0.2, -0.2,
]), gl.STATIC_DRAW);

gl.enableVertexAttribArray(positionLoc);
gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);

const deg = v => v * Math.PI / 180;

// setup matrixes, one per instance
const numInstances = 5;
const matrixBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, matrixBuffer);
// just allocate the buffer
gl.bufferData(gl.ARRAY_BUFFER, numInstances * 16 * 4, gl.DYNAMIC_DRAW);

// set all 4 attributes for matrix
for (let i = 0; i < 4; ++i) {
gl.enableVertexAttribArray(matrixLoc + i);
// note the stride and offset
gl.vertexAttribPointer(matrixLoc + i, 4, gl.FLOAT, false, 64, i * 16);
// this line says this attribute only changes for each 1 instance
gl.vertexAttribDivisor(matrixLoc + i, 1);
}

// setup colors, one per instance
const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
1, 0, 0, 1,
0, 1, 0, 1,
0, 0, 1, 1,
1, 0, 1, 1,
0, 1, 1, 1,
]), gl.DYNAMIC_DRAW);

// set all attribute for color
gl.enableVertexAttribArray(colorLoc);
gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
// this line says this attribute only changes for each 1 instance
gl.vertexAttribDivisor(colorLoc, 1);

// make a typed array with one view per matrix
const matrixData = new Float32Array(numInstances * 16);
const matrices = [];
for (let i = 0; i < numInstances; ++i) {
matrices.push(new Float32Array(matrixData.buffer, i * 16 * 4, 16));
}

function render(time) {
time *= 0.001; // seconds

// update all the matrices
matrices.forEach((mat, ndx) => {
m4.translation([-0.5 + ndx * 0.25, 0, 0], mat);
m4.rotateZ(mat, time * (0.1 + 0.1 * ndx), mat);
});

// upload the new matrix data
gl.bindBuffer(gl.ARRAY_BUFFER, matrixBuffer);
gl.bufferSubData(gl.ARRAY_BUFFER, 0, matrixData);

gl.bindVertexArray(vao);
gl.useProgram(program);
gl.uniformMatrix4fv(viewProjectionLoc, false, m4.identity());
gl.drawArraysInstanced(
gl.TRIANGLES,
0, // offset
3, // num vertices per instance
numInstances, // num instances
);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
canvas { border: 1px solid black; }
<script src="https://twgljs.org/dist/4.x/twgl-full.min.js"></script>
<canvas></canvas>

关于webgl2 - 如何使用统一缓冲区对象和实例化渲染来绘制多个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58568278/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com