代码之家  ›  专栏  ›  技术社区  ›  Maverick Meerkat

缓冲区和glVertexAttribute指针之间的关系

  •  1
  • Maverick Meerkat  · 技术社区  · 7 年前

    glGenBuffers , glBindData , glBufferData glBufferSubData ]及 glVertexAttribPointer .

    glvertexattributepointer FloatBuffer 在这种情况下)

    GLES20.glVertexAttribPointer(positionHandle, 3, GLES20.GL_FLOAT, false, 12, vertexBuffer);
    GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 16, colorBuffer);
    GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 12, normalsBuffer);
    GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 8, textureBuffer);
    

    1) 我为什么要使用缓冲区方法?仅当我的数据碰巧堆叠在一个数组中时?

    2) openGL如何在幕后处理这些直接(非缓冲)函数?我看到它在呼叫 glVertexAttribPointerBounds -它实际上是否将其堆叠到单个字节数组中?

    3) 如果我将数组绑定到 GL_ARRAY_BUFFER -这意味着我必须使用堆叠阵列版本,我将无法传递更多的直接对象,对吗?i、 e.我不能这样做:

    int[] bufferVertices = new int[1];
    GLES20.glGenBuffers(1, bufferVertices, 0);
    vertexBufferId = bufferVertices[0];
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4 , vertexBuffer, GLES20.GL_STATIC_DRAW);
    
    GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, vertexStride,0);
    GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 16, colorBuffer);
    GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false,12, normalsBuffer);
    GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false,8, textureBuffer);
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Rabbid76    7 年前

    glVertexAttribPointer glvertexattributepointer 被视为对此缓冲区的偏移,但如果未绑定顶点缓冲区对象,则最后一个参数将被视为指向数据的指针:

    OpenGL ES 2.0 specification; 2.8. VERTEX ARRAYS; 21 :

    void VertexAttribPointer( uint index, int size, enum type, 
                              boolean normalized,  sizei stride, 
                              const void *pointer );
    

    对于每个命令, 指针 指定要指定的数组的第一个元素的第一个值在内存中的位置。

    看见 OpenGL ES 2.0 specification; 2.9. BUFFER OBJECTS; 25 :

    ... 当数组源于 缓冲区对象,即 该数组的值用于计算进入缓冲区对象数据存储的偏移量(以基本机器单位表示)。。。

    这意味着可以执行以下操作:

    int[] bufferVertices = new int[4];
    GLES20.glGenBuffers(4, bufferVertices, 0);
    
    vertexBufferId = bufferVertices[0];
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, vertexBuffer, GLES20.GL_STATIC_DRAW);
    
    colorBufferId = bufferVertices[1];
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, colorBufferId);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, colorBuffer, GLES20.GL_STATIC_DRAW);
    
    normlBufferId = bufferVertices[2];
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normlBufferId);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, normalsBuffer, GLES20.GL_STATIC_DRAW);
    
    textureBufferId = bufferVertices[3];
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, textureBufferId);
    GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, cubeCoords.length * 4, textureBuffer, GLES20.GL_STATIC_DRAW);
    

    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vertexBufferId);
    GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, 0, 0);
    
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, colorBufferId);
    GLES20.glVertexAttribPointer(colorHandle, 4, GLES20.GL_FLOAT, false, 0, 0);
    
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, normlBufferId);
    GLES20.glVertexAttribPointer(normalHandle, 3, GLES20.GL_FLOAT, false, 0, 0);
    
    GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, textureBufferId);
    GLES20.glVertexAttribPointer(textureHandle, 2, GLES20.GL_FLOAT, false, 0, 0);
    
        2
  •  0
  •   Vlad Alex    7 年前

    1) 首选的方法是尽可能使用缓冲区对象。这确保了预先分配必要的GPU资源。但是,对于动态几何体,调用无缓冲区方法有时更方便。根据我的经验,一些驱动程序使用无缓冲区的方法比使用带有GLES20.GL_DYNAMIC_DRAW的缓冲区表现出更好的性能。但对于静态几何体,最好的方法是使用GL缓冲区。这样,驱动程序可以避免在每次绘制调用之前复制顶点数据。

    3) GL缓冲区和CPU阵列流的混合应该可以正常工作。这是一种常见的场景,其中一部分顶点数据是静态的(例如texcoords),另一部分是动态的(例如位置),后者由CPU进行转换。