【问题标题】:Change colour of vertices after they are uploaded using a VBO使用 VBO 上传顶点后更改顶点的颜色
【发布时间】:2013-01-29 02:24:08
【问题描述】:

编辑: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);
}

虽然上面的代码有效,但它消耗了很多电池,所以现在我尝试用 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);
}

【问题讨论】:

    标签: iphone objective-c opengl-es opengl-es-2.0 vbo


    【解决方案1】:

    视情况而定。 (好词,不是吗?适用于所有情况。)

    如果您确实需要以不可预知的方式改变每个顶点的颜色,那么每次绘制它们时,您都需要在每一帧上传顶点颜色。将顶点位置放在它们自己的(静态)VBO 中是一个不错的选择,因为这允许您重复使用而无需每次都上传(系统内存 GPU 内存带宽始终是宝贵的商品),但是任何将 改变,嗯,将 改变。

    如果您可以通过编程计算每个顶点的颜色,那么vertex shaders 就可以派上用场了。 (确实,它们的目的是什么!)希望每个顶点的颜色是以下组合的某种函数:

    1. 每个顶点的静态数据。您可以在 VBO 中上传一次并重复使用。
    2. 整个阵列的全局变量数据。您为此使用shader uniforms,每次抽奖只需上传一次。
    3. 也许vertex textures,如果您的平台支持?

    然后,您可以编写一个顶点着色器,根据这些输入计算颜色,并且每一帧您只需要重新指定着色器制服——通常总共有十几个浮点数。

    所以这取决于你希望你的颜色如何改变。如果您可以使用顶点着色器,那么您确实可以在每次绘制时跳过上传。如果您不能和/或突变过于复杂或任意而无法在顶点着色器中执行 - 您只需要在 CPU 端执行此操作,然后咬紧牙关。

    【讨论】:

    • 从未听说过顶点纹理;顶点程序中的纹理获取?好像已经加入SM3了。
    • 就个人而言,我会选择顶点纹理。要在顶点着色器中进行纹理查找,您应该使用texture2DLod()。请参考 GLSL ES 2.0 规范的 8.7 Texture Lookup Functions 部分:khronos.org/files/opengles_shading_language.pdf
    • 假设我不使用着色器并且每帧重新上传颜色。我必须上传整个网格的颜色数组,还是只能发送改变的顶点颜色?
    • 但也许我可以使用着色器。网格中的每个单元格可以处于以下两种状态之一:开和关(黑色和白色)。我将这些状态保存在一个数组中。如果有 2 个或 3 个相邻单元格开启,则该单元格开启,否则关闭。这个逻辑可以在着色器中处理吗?
    • @dene:你必须重新上传整个颜色数组;没有挑选和选择。但是,您的特定逻辑将难以封装在着色器中,因为着色器的调用是独立的并且不共享信息。也许为此发布另一个问题?
    猜你喜欢
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 2019-03-17
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多