【问题标题】:How color attributes work in VBO?颜色属性在 VBO 中如何工作?
【发布时间】:2010-05-07 00:13:18
【问题描述】:

我正在编写 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;

【问题讨论】:

  • 好的,我认为上面的示例代码多次定义了相同的顶点。如您所见,一个立方体有 8 个顶点,但这段代码有 24 个。这就是它为同一顶点指定 3 种不同颜色的方式,具体取决于它属于哪个面。这是唯一的方法吗?是不是太浪费了?

标签: opengl-es webgl


【解决方案1】:

我喜欢看它的方式是每个顶点不是空间中的一个点,而是一组属性。这些通常(但不总是)包括它的位置,可能包括它的颜色、纹理坐标等等等。三角形(或线,或其他基元)通过指定一个集合来定义顶点,然后通过对每个顶点的值进行线性插值,为每个像素的每个属性生成值。

正如利亚姆所说,正如您在评论中所意识到的那样,这意味着如果您想在空间中有一个点供多个图元的顶点使用——例如,立方体的角——由于其他非位置属性因每个基元而异,因此每个属性组合都需要一个单独的顶点。

这在某种程度上会浪费内存——但以任何其他方式执行此操作所涉及的复杂性会使事情变得更糟,并且需要图形硬件做更多的工作来解包和重新打包数据。对我来说,感觉浪费与我们通过为视频内存中的每个像素使用 32 位 RGBA 值而不是保留我们想要使用的每种颜色的“调色板”查找表然后只存储一个索引到每个像素(当然,这是我们过去在 RAM 更昂贵时所做的)。

【讨论】:

    【解决方案2】:

    如果一组多边形的颜色相同,则所有多边形共享的顶点及其颜色可以定义一次并由多边形共享(使用索引)。

    如果多边形的颜色不同,那么即使一个顶点的位置可能是共同的,但颜色却不是,因此不能共享整个顶点。您需要为每个多边形定义顶点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2015-07-23
      相关资源
      最近更新 更多