代码之家  ›  专栏  ›  技术社区  ›  Community wiki

颜色属性如何在VBO中工作?

  •  5
  • Community wiki  · 技术社区  · 2 年前

    我正在编写OpenGL ES 2.0(Webgl)的代码。我正在使用VBO绘制基元。我有顶点数组,颜色数组和索引数组。我看过示例代码、书籍和教程,但有一件事我不明白——如果颜色是按顶点定义的,它会如何影响与这些顶点相邻的多边形曲面?(我是OpenGL(ES)的新手)

    我将举例说明。我有一个立方体要画。根据我在OpenGLES书中所读到的内容,颜色被定义为顶点属性。在这种情况下,如果我想用6种不同的颜色绘制立方体的6个面,我应该如何定义颜色。我感到困惑的原因是:每个顶点对3个面都是公共的,那么它将如何帮助定义每个顶点的颜色?(或者应该根据索引定义颜色?)。事实上,我们需要将这些面细分为三角形,这让我更难理解这种关系是如何运作的。同样的困惑也适用于边缘。假设我想使用LINES基元绘制边,而不是绘制三角形。每个边缘都有不同的颜色。在这种情况下,我应该如何定义颜色属性?

    我很少看到工作实例。特别是本教程: http://learningwebgl.com/blog/?p=370

    我在上面的例子中看到了如何定义颜色数组来绘制一个有6个不同颜色面的立方体,但我不明白为什么要这样定义。(例如,为什么每种颜色都被复制4次到未包装的颜色中?)

    有人能解释颜色属性在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;
    
    2 回复  |  直到 16 年前
        1
  •  9
  •   Giles Thomas    16 年前

    我喜欢这样看,每个顶点不是空间中的一个点,而是一束属性。这些通常(但并不总是)包括其位置和 也许 包括其颜色、纹理坐标等。通过指定一组顶点来定义三角形(或直线或其他图元),然后通过线性插值每个顶点的值来为每个像素的每个属性生成值。

    正如Liam所说,正如你在评论中所意识到的,这意味着如果你想在空间中有一个点被多个基元的顶点使用,例如立方体的角,而其他非位置属性在每个基元的基础上变化,你需要为每个属性组合都有一个单独的顶点。

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

        2
  •  3
  •   Liam    16 年前

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

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