我是 WebGL 的新手,我正在尝试学习 WebGL2。但我真的不明白如何使用 WebGL。特别是 VAO 和 VBO。我寻找有关内存工作原理的图表,但找不到。我给出了以下示例,我将尝试解释该示例的工作原理。
function main(){
// initialize GL
// create vertex shader and fragment shader
// create program
var positionAttributeLocation = gl.getAttribLocation(program, "a_position");
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
// define positions with array
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
var vao = gl.createVertexArray();
gl.bindVertexArray(vao);
gl.enableVertexAttribArray(positionAttributeLocation);
// ....
gl.vertexAttribPointer(
positionAttributeLocation, size, type, normalize, stride, offset
);
gl.viewport(0, 0, 400, 300);
// clear canvas
// use program
gl.bindVertexArray(vao); // why we use that here ?
var primitiveType = gl.TRIANGLES;
var offset = 0;
var count = 3;
gl.drawArrays(primitiveType, offset, count);
}
Run Code Online (Sandbox Code Playgroud)
bindBuffer()功能的激活缓冲区。bindVertexArray().vertexAttribFunction().这是我能理解的情况。然后情况变得混乱。为什么我们再次调用bindVertexArray(vao)?是否还有关于 VAO 和 VBO 在 WebGL 中如何工作的详细方案?
在 WebGL 中绘制单个对象是不正常的。如果您有 1 个以上的对象并且您正在使用顶点数组对象 (VAO),那么
在初始化时间
for each object
create a vertex array object VAO and bind it
create all the buffers for this object
setup all the attributes for this object
Run Code Online (Sandbox Code Playgroud)
在抽奖时
for each object
bind the VAO for this object
set uniforms for this object (and optionally bind textures for this object)
draw
Run Code Online (Sandbox Code Playgroud)
所以是的,如果你只画一个东西,那么绑定 VAO 两次可能看起来很奇怪,但是在初始化时绑定一次 VAO 一次和在绘制时再次绑定的模式是正常的事情,因为正常的事情是绘制多个对象。
请注意,这与任何其他有状态 API 没有什么不同。例如画布 2d API。你可以写这个
ctx.fillStyle = 'red';
function renderLoop(time) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillRect(x, y, 20, 20); // assume X and Y are animated
...
}
Run Code Online (Sandbox Code Playgroud)
但是,只画一件东西是不正常的,所以大多数人,即使他们只从一件东西开始也会这样做
function renderLoop(time) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillStyle = 'red';
ctx.fillRect(x, y, 20, 20); // assume X and Y are animated
...
}
Run Code Online (Sandbox Code Playgroud)
即使设置fillStyle每一帧是多余的。他们这样做是因为他们希望以后能画更多的东西,所以在你画之前设置与你想画的东西相关的状态就变成了一种模式。
function renderLoop(time) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillStyle = 'red';
ctx.fillRect(x, y, 20, 20); // assume X and Y are animated
ctx.fillStyle = 'blue';
ctx.fillRect(x2, y2, 20, 20); // assume x2 and y2 are animated
...
}
Run Code Online (Sandbox Code Playgroud)