为什么我们使用两次 bindVertexArray(vao)?
Why are we use twice bindVertexArray(vao)?
我是 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);
}
- 首先,我在顶点着色器程序中获得了属性,我们将用于 VAO。我可以认为它是插槽 0.
- 然后我为位置(数组)创建了缓冲区。
- 已激活具有
bindBuffer()
功能的缓冲区。
- 然后在缓冲区中添加位置。
- 创建 VAO 并使用
bindVertexArray()
激活。
- 启用插槽 0,我将在插槽 0 中添加数据(位置)。它作为
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
开奖时
for each object
bind the VAO for this object
set uniforms for this object (and optionally bind textures for this object)
draw
所以是的,如果您只绘制一个东西,那么绑定 VAO 两次可能看起来很奇怪,但是在初始化时绑定一次 VAO 并在绘制时再次绑定的模式是正常的事情,因为正常情况下要做的就是绘制多个对象。
请注意,这与任何其他有状态 API 没有什么不同。例如 canvas 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
...
}
但是只画一件东西也是不正常的,所以大多数人,即使他们只从一件东西开始也会这样做
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
...
}
尽管每帧都设置 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
...
}
我是 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);
}
- 首先,我在顶点着色器程序中获得了属性,我们将用于 VAO。我可以认为它是插槽 0.
- 然后我为位置(数组)创建了缓冲区。
- 已激活具有
bindBuffer()
功能的缓冲区。 - 然后在缓冲区中添加位置。
- 创建 VAO 并使用
bindVertexArray()
激活。 - 启用插槽 0,我将在插槽 0 中添加数据(位置)。它作为
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
开奖时
for each object
bind the VAO for this object
set uniforms for this object (and optionally bind textures for this object)
draw
所以是的,如果您只绘制一个东西,那么绑定 VAO 两次可能看起来很奇怪,但是在初始化时绑定一次 VAO 并在绘制时再次绑定的模式是正常的事情,因为正常情况下要做的就是绘制多个对象。
请注意,这与任何其他有状态 API 没有什么不同。例如 canvas 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
...
}
但是只画一件东西也是不正常的,所以大多数人,即使他们只从一件东西开始也会这样做
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
...
}
尽管每帧都设置 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
...
}