我正在编码 OpenGL ES 2.0 (Webgl)。我正在使用 VBO 来绘制基元。我有顶点数组、颜色数组和索引数组。我看过示例代码、书籍和教程,但有一件事我不明白 - 如果每个顶点都定义了颜色,那么它如何影响与这些顶点相邻的多边形表面? (我是 OpenGL(ES) 的新手)
我会用一个例子来解释。我有一个立方体要画。根据我在 OpenGLES 书中读到的内容,颜色被定义为顶点属性。在这种情况下,如果我想用 6 种不同的颜色绘制立方体的 6 个面,我应该如何定义颜色。我困惑的根源是:每个顶点都是 3 个面所共有的,那么它如何帮助定义每个顶点的颜色? (或者应该根据索引定义颜色?)。事实上,我们需要将这些面分割为三角形,这让我更难理解这种关系是如何运作的。同样的困惑也适用于边缘。假设我想使用 LINES 图元来绘制边缘,而不是绘制三角形。每个边缘颜色不同。在这种情况下我应该如何定义颜色属性?
我见过很少的工作示例。具体来说,本教程:http://learningwebgl.com/blog/?p=370
我看到上面的示例中如何定义颜色数组来绘制具有 6 个不同颜色面的立方体,但我不明白为什么要这样定义。 (例如,为什么每种颜色要复制 4 次到 unpackedColors 中?)
有人可以解释一下颜色属性在 VBO 中如何工作吗?
[上面的链接似乎无法访问,所以我将相关代码贴在这里]
cubeVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer);
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 WebGLFloatArray(vertices), gl.STATIC_DRAW);
cubeVertexPositionBuffer.itemSize = 3;
cubeVertexPositionBuffer.numItems = 24;
cubeVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexColorBuffer);
var colors = [
[1.0, 0.0, 0.0, 1.0], // Front face
[1.0, 1.0, 0.0, 1.0], // Back face
[0.0, 1.0, 0.0, 1.0], // Top face
[1.0, 0.5, 0.5, 1.0], // Bottom face
[1.0, 0.0, 1.0, 1.0], // Right face
[0.0, 0.0, 1.0, 1.0], // Left face
];
var unpackedColors = []
for (var i in colors) {
var color = colors[i];
for (var j=0; j < 4; j++) {
unpackedColors = unpackedColors.concat(color);
}
}
gl.bufferData(gl.ARRAY_BUFFER, new WebGLFloatArray(unpackedColors), gl.STATIC_DRAW);
cubeVertexColorBuffer.itemSize = 4;
cubeVertexColorBuffer.numItems = 24;
cubeVertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer);
var cubeVertexIndices = [
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
]
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new WebGLUnsignedShortArray(cubeVertexIndices), gl.STATIC_DRAW);
cubeVertexIndexBuffer.itemSize = 1;
cubeVertexIndexBuffer.numItems = 36;
最佳答案
我喜欢这样看待它:每个顶点不是空间中的一个点,而是一组属性。这些通常(但不总是)包括它的位置,可能包括它的颜色、纹理坐标等。三角形(或线,或其他图元)是通过指定一组来定义的顶点,然后通过线性插值每个顶点值来生成每个像素处每个属性的值。
正如 Liam 所说,正如您在评论中所意识到的那样,这意味着如果您希望空间中的一个点被顶点用于多个图元(例如,立方体的角),由于其他非位置属性因基元而异,因此您需要为每个属性组合提供一个单独的顶点。
这在某种程度上浪费了内存 - 但以任何其他方式执行此操作所涉及的复杂性会使事情变得更糟,并且需要图形硬件做更多的工作来解包和重新打包数据。对我来说,这种浪费与我们为视频内存中的每个像素使用 32 位 RGBA 值而不是为我们想要使用的每种颜色保留一个“调色板”查找表然后仅存储一个索引到每个像素(当然,这就是我们在 RAM 更昂贵时所做的事情)。
关于opengl-es - 颜色属性在 VBO 中如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2775608/