c - OpenGL ES 2.0 + 开罗 : HUD

标签 c opengl-es-2.0 hud

我正在尝试在 ARM Linux 平台上通过用 C 语言编写的 OpenGL ES 2.0 应用程序渲染 HUD。

我目前正在使用靠近近裁剪平面放置的 2 个三角形,并将纹理平铺到它们上面。纹理是屏幕的大小,除了我渲染文本的部分外,大部分是透明的。纹理是使用Pango/Cairo生成的

如果我打开 HUD(取消对 render_ui 调用的注释),我目前会受到 50% 的性能影响(从 60fps 到 30fps)。

这是渲染 HUD 的代码:

void render_ui(OGL_STATE_T *state) {

    glUseProgram(state->uiHandle);

    matIdentity(modelViewMatrix);
    matTranslate(modelViewMatrix, 0, 0, -0.51);

    const GLfloat *mvMat2 = modelViewMatrix;

    glViewport(0,0,state->screen_width, state->screen_height);

    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glBindBuffer(GL_ARRAY_BUFFER, state->uiVB);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state->uiIB);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, state->uiTex);
    glUniform1i(_uiTexUniform, 0);

    glUniformMatrix4fv(_uiProjectionUniform, 1, 0, pMat);
    glUniformMatrix4fv(_uiModelViewUniform, 1, 0, mvMat2);

    glVertexAttribPointer(_uiPositionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); 
    glVertexAttribPointer(_uiColorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
            (GLvoid *) (sizeof(GLfloat) * 3));
    glVertexAttribPointer(_uiTexCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
            (GLvoid *) (sizeof(GLfloat) * 7));

    glEnableVertexAttribArray(_uiPositionSlot);
    glEnableVertexAttribArray(_uiColorSlot);
    glEnableVertexAttribArray(_uiTexCoordSlot);

    glDrawElements(GL_TRIANGLES, uiIndicesArraySize / uiIndicesElementSize,
            GL_UNSIGNED_BYTE, 0);   

    glDisableVertexAttribArray(_uiTexCoordSlot);
    glDisable(GL_BLEND);

    GLenum err;

    if ((err = glGetError()) != GL_NO_ERROR)
        printf("There was an error");
}

必须有更明智的方法来做到这一点。

最佳答案

在移动设备上,GPU 对混合非常敏感,这有多种原因:

  • 混合会消耗更多带宽(需要读取当前像素以将其与新像素混合)
  • 混合可以打破隐藏表面去除优化
  • 混合还可以打破基于图 block 的延迟渲染优化

简而言之,移动 GPU 喜欢不透明的多边形,讨厌透明的

请注意,屏幕上透明多边形占据的总表面也非常重要,因为大多数移动 GPU 具有“基于图 block ”的特性(当图 block / block 被透明多边形覆盖时,您可以为此失去了一些 GPU 优化)。

另外,既然你说你从 60fps 急剧下降到 30fps,我会得出结论,你的设备 GPU 正在阻塞,等待屏幕 60Hz 垂直同步交换,所以这意味着你的帧 DT 只能是16 毫秒,因此您可能只能获得 fps 值,例如:60、30、15、7.5,...

因此,如果您的帧率为 60fps,但在您的应用程序主循环中添加一些内容,这会将理论 fps 降至仅 57fps,然后由于垂直同步等待,您将突然变为 30fps。可以禁用 VSync,或者可以使用三重缓冲等技术来缓解这种情况,但是对于 OpenGLES,这样做的方式是特定于您正在使用的操作系统和硬件的……没有“官方的工作方式”在所有设备上”。

所以,了解所有这些后,我们提出了一些恢复到 60fps 的建议:

  1. 使用降低的分辨率,例如:1280x720 而不是 1920x1080,这将减少带宽使用和片段处理。当然不理想,但这可以用作确认您有带宽或片段问题的测试(如果在降低分辨率后恢复 60fps,则说明您有此类问题)
  2. 使用 16 位 (R5G6B5) 后备缓冲区而不是 32 位后备缓冲区 (R8G8B8A8),这可以减少带宽使用,但会损失一些视觉质量
  3. 减少混合表面的面积:在您的情况下,这意味着您应该按“ block ”组织文本,每个 block 尽可能适合文本,如 IOS 图片中的文本 docs : enter image description here
  4. 想办法在您的设备上禁用垂直同步/使用三重缓冲。如果您可以访问 Vivante GPU 文档(我没有),这可能会在里面进行描述。

第 3 点是最好的做法(这是我开发的大多数手机游戏所做的),但是这需要一些不可忽略的额外工作。第 1、2 和 3 点更直接,但只是“一半的解决方案”。

关于c - OpenGL ES 2.0 + 开罗 : HUD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32345164/

相关文章:

java - 用 Java 填充 HUD

objective-c - 使用 Cocoa 在另一个应用程序之上创建 HUD

c++ - 如何在 VisualDsp++ 5 中为 Blackfin BF537 使用 *.cpp 文件中的 asm 实现的函数?

c - 来自 math.h 的函数日志返回错误

objective-c - Mac OSX 覆盖

android - 设置gl_PointSize导致的闪屏/全黑屏

ios - OpenGL ES 纹理质量下降

c++ - 在函数调用之前使用 (void)

c - 指向指针的指针段错误

ios - GL_APPLE_shader_framebuffer_fetch gl_lastFragData