我对 ARRAY_INDEX_BUFFER (索引缓冲区)与 ARRAY_BUFFER (阵列缓冲区)的使用感到困惑,我正在寻求澄清/更好理解。
具体来说,我对如何(假设存在多个数组缓冲区)感到困惑,WebGL和索引缓冲区如何知道要引用哪个数组缓冲区?*
使用从Mozilla's Creating 3D objects using WebGL Demo获得的代码作为基础,我理解数组缓冲区已分配并初始化为
cubeVerticesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
var vertices = [
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
然后索引存储在索引缓冲区中
cubeVerticesIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // back
8, 9, 10, 8, 10, 11, // top
12, 13, 14, 12, 14, 15, // bottom
16, 17, 18, 16, 18, 19, // right
20, 21, 22, 20, 22, 23 // left
]
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW);
但鉴于还有一个颜色数组缓冲区定义为
var colors = [
1.0, 1.0, 1.0, 1.0, // Front face: white
1.0, 0.0, 0.0, 1.0, // Back face: red
0.0, 1.0, 0.0, 1.0, // Top face: green
0.0, 0.0, 1.0, 1.0, // Bottom face: blue
1.0, 1.0, 0.0, 1.0, // Right face: yellow
1.0, 0.0, 1.0, 1.0 // Left face: purple
];
var generatedColors = [];
for (j=0; j<6; j++) {
var c = colors[j];
for (var i=0; i<4; i++) {
generatedColors = generatedColors.concat(c);
}
}
cubeVerticesColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesColorBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(generatedColors), gl.STATIC_DRAW);
但是一旦进入绘图程序,排序就是
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesBuffer);
gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVerticesColorBuffer);
gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVerticesIndexBuffer);
gl.drawElements(gl.TRIANGLES, 36, gl.UNSIGNED_SHORT, 0);
我假设 bindBuffer 方法告诉WebGL&#34;状态机&#34;制作通用缓冲区&#34;活跃&#34;并且 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER 根据当前的通用缓冲区激活新的索引缓冲区
不知何故,我不认为我对正在发生的事情的理解是完全正确的。任何澄清将不胜感激。具体来说,我希望在某些时候添加其他对象,使用不同的缓冲区(比如球形或圆环形,以及其他颜色方案)
但是我理解 drawElements()只是基于索引绘制而不是 drawArrays(
>完成的实际数组)正确?
答案 0 :(得分:0)
gl.vertexAttribPointer
告诉webgl当前由gl.bindBuffer
绑定的缓冲区中预期的数据类型。然后在着色器中编写您希望如何使用缓冲区中提供的数据。
有点像这样。假设在着色器中我想使用2个缓冲区A和B,其中我想要每个顶点3浮点数A和2个浮点数来自B。
gl.bufferData
向GPU发送连续浮点数组*,GPU不知道如何解释连续浮点数组。
所以我需要使用gl.vertexAttribPointer
来告诉GPU如何格式化数据,这基本上就是它的作用。
但是,编写webgl / opengl API的方式不仅仅是bufferA.vertexAttribPointer()
,而是我必须首先使用'gl.bindBuffer'设置一个虚构的全局变量BOUND_BUFFER
。然后你可以想象vertexAttribPointer
被实现为对全局BOUND_BUFFER
“实例”进行操作“并做任何需要做的事情。
答案 1 :(得分:0)
OpenGL和变体(WebGL等)的隐藏诅咒是状态机。当您调用glBindBuffer(GL_ARRAY_BUFFER, buffer)
时,状态机会将buffer
设置为活动数组缓冲区。同样,当您调用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexbuffer)
时,状态机会将indexbuffer
设置为活动元素数组缓冲区(或活动索引缓冲区)。
调用glVertexAttribPointer
时,给定属性索引的数据来自活动数组缓冲区。这正是您在上一个代码段中描述的内容。当您发出绘图调用(例如glDrawElements
)时,活动索引缓冲区用于索引属性。
具体来说,我对如何(假设存在多个数组缓冲区)感到困惑,WebGL和索引缓冲区如何知道要引用哪个数组缓冲区?
最重要的一点是,单个顶点不仅仅是它的位置,而是所有属性的组合。在您的情况下,位置和颜色组成一个顶点。现在,查看您指定的属性:
Position: | pos0 | pos1 | pos2 | pos3 | pos4 | pos5 | pos6 |
Color: | color0 | color1 | color2 | color3 | color4 | color5 | color6 |
索引缓冲区中的每个索引都指向position和color属性的组合。也就是说,索引0将获取pos0
和color0
;索引5将获取pos5
和color5
。
要回答您的问题,索引缓冲区指的是调用glVertexAttribPointer
时引用的所有数组缓冲区。
(严格来说,索引缓冲区是指所有已启用的属性。glVertexAttribPointer
的最后一个参数允许您指定活动数组缓冲区的偏移量,以便可以来到多组属性来自相同的数组缓冲区。)