使用VBO上传顶点后更改颜色

sid*_*ick 2 iphone opengl-es objective-c vbo opengl-es-2.0

编辑:Apple的工作编码示例在此链接中找到:http: //developer.apple.com/library/ios/#documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/TechniquesforWorkingwithVertexData/TechniquesforWorkingwithVertexData.html

在为200 x 200个正方形的固定网格创建顶点之后,我通过使用VBO将顶点发送到GPU来渲染它.我怎样才能更新顶点的颜色?数百个顶点的颜色会频繁变化 - 每隔几帧.

我以前解决了不使用VBO的问题.我创建了顶点和颜色数组,并使用以下代码渲染顶点.我通过更新数组改变了顶点的颜色triangleColours:

-(void)render {

    glClearColor(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
    glClear(GL_COLOR_BUFFER_BIT);

    [effect prepareToDraw];

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 2,
                          GL_FLOAT, GL_FALSE, 0, triangleVertices);

    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4,
                          GL_FLOAT, GL_FALSE, 0, triangleColours);


    glDrawArrays(GL_TRIANGLES, 0, numTriangleVertices);

    glDisableVertexAttribArray(GLKVertexAttribPosition);
    glDisableVertexAttribArray(GLKVertexAttribColor);
}
Run Code Online (Sandbox Code Playgroud)

虽然上面的代码有用,但它吃了很多电池,所以现在我正试着用VBO做.顶点不会改变位置,所以我理解VBO是一个很好的选择,但是如何改变顶点的颜色呢?

这是我目前的代码简化为只绘制一个方块:

编辑:我如何更新下面的代码,以便它们更改时只上传顶点颜色?VBO设置代码和绘图代码应该如何变化?如何更新我的verticesColours颜色数组然后调用glBufferSubData()?

    // Setup vertices and VBO

    // Vertices for a single square

    const Vertex Vertices[] = {

        // position and colour
        {{-20, -20}, {1, 1, 1, 1}},
        {{-20, -20}, {1, 1, 1, 1}},
        {{-20, -20}, {1, 1, 1, 1}},
        {{-20, -20}, {1, 1, 1, 1}},
    };

    const GLubyte Indices[] = {

        0, 1, 2,
        2, 3, 0,
    };

    numIndices = sizeof(Indices)/sizeof(Indices[0]);

    [EAGLContext setCurrentContext:self.context];

    glEnable(GL_CULL_FACE);

    self.effect = [[GLKBaseEffect alloc] init];

    self.effect.transform.projectionMatrix = GLKMatrix4MakeOrtho(-50.0, 50.0,
                                                                 -50.0, 50.0,
                                                                  0.0, 1.0);


    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);        
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Position));
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) offsetof(Vertex, Color));

    glBindVertexArrayOES(0);


// Render

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);

    [self.effect prepareToDraw];    

    glBindVertexArrayOES(_vertexArray);   
    glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_BYTE, 0);
}
Run Code Online (Sandbox Code Playgroud)

she*_*heu 6

要看.(好的,不是吗?适用于所有情况.)

如果你真的需要以不可预测的方式改变每个顶点的颜色,每次绘制它们,那么你需要每帧上传顶点颜色.将顶点位置放在它们自己的(静态)VBO中是一个不错的选择,因为它允许您重复使用而不必每次都上传(系统内存< - > GPU内存带宽始终是一种宝贵的商品),但任何必须改变的东西,好吧,将不得不改变.

但是,如果您可以通过编程方式计算每个顶点的颜色,那么这就是顶点着色器派上用场的地方.(的确,他们的目的是什么!)希望每个顶点的颜色是某些组合的功能:

  1. 静态每顶点数据.您可以在VBO中上传一次并重复使用.
  2. 整个阵列中的全局变量数据.你可以使用着色器制服,只需为每次绘制上传一次.
  3. 也许是顶点纹理,如果你的平台支持那个?

然后,您可以编写一个顶点着色器来计算这些输入的颜色,每个帧只需要重新指定着色器制服 - 通常大约十几个浮点数.

所以这取决于你想要改变颜色的方式.如果你可以使用顶点着色器,那么你确实可以在每次绘制时跳过上传.如果你不能和/或突变在顶点着色器中太复杂或任意 - 你只需要做那个CPU端,并咬上传子弹.

  • 就个人而言,我会选择顶点纹理.要在顶点着色器中进行纹理查找,您应该使用`texture2DLod()`.请参阅GLSL ES 2.0规范*8.7纹理查找功能*章节:http://www.khronos.org/files/opengles_shading_language.pdf (2认同)