6

我对在 OpenGL 中使用带纹理的三角形网格绘制全屏背景时看到的糟糕性能感到非常困惑:使用最基本的着色器仅绘制背景而没有其他任何东西的最大速度为 40 fps,使用默认设置为 50 fps管道。

虽然 40 fps 似乎并不算太​​糟糕,但在此之上添加任何其他东西会使 fps 下降,并且考虑到我需要在此之上绘制 100-200 个其他网格,我最终得到了一个微不足道的 15 fps,这根本不是可用。

我已经将相关代码隔离到一个可用的 XCode 项目,但它的本质是规范的纹理贴图示例:

static const GLfloat squareVertices[] = {
    -1.0f, -1.0f,
    1.0f, -1.0f,
    -1.0f,  1.0f,
    1.0f,  1.0f,
};
static const GLfloat texCoords[] = {
    0.125, 1.0,
    0.875, 1.0,
    0.125, 0.0,
    0.875, 0.0
};


glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);

if ([context API] == kEAGLRenderingAPIOpenGLES2) {
    // Use shader program.
    glUseProgram(program);

    glActiveTexture(GL_TEXTURE0);
    glUniform1i(uniforms[UNIFORM_TEXTURE], 0);
    glBindTexture(GL_TEXTURE_2D, texture);

    // Update attribute values.
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    glVertexAttribPointer(ATTRIB_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
    glEnableVertexAttribArray(ATTRIB_TEXCOORD);
} else {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    glEnable( GL_TEXTURE_2D );
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); 

    glVertexPointer(2, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

顶点着色器:

attribute lowp vec4 position;
attribute lowp vec2 tex;

varying lowp vec2 texCoord;

uniform float translate;

void main()
{
    gl_Position = position;
    texCoord = tex;
}

片段着色器:

varying lowp vec2   texCoord;
uniform sampler2D   texture;

void main()
{
    gl_FragColor = texture2D(texture, texCoord);
}

将矩形大小除以 2 会使帧速率加倍,因此渲染时间显然取决于绘图在屏幕上占用的空间。这完全有道理,但对我来说没有意义的是,似乎不可能用超过 15 fps 的 OpenGL 纹理映射网格覆盖整个屏幕。

然而,那里有数百个游戏可以做到这一点,所以这是可能的,我一定做错了什么,但它是什么?

4

2 回答 2

7

不幸的是,我现在只有我的 iPad 2 来测试这个(我的 iPad 1 测试单元坐在家里),它的片段处理速度快得离谱。它被固定在 60 FPS,您的日志记录中的理论 FPS 为 1400。

但是,我使用 OpenGL ES Driver 和 Time Profiler 工具以及酷炫的新 OpenGL ES Analyzer(Xcode 4 附带)通过 Instruments 运行它。OpenGL ES Analyzer 的结果如下所示:

OpenGL ES 分析器

查看 OpenGL ES 驱动程序中的 Tiler Utilization 统计数据显示,tiler 几乎没有被使用,但渲染器有一些用处(同样,在我的 iPad 2 上只有 5%)。这表明为您的几何图形使用 VBO 和索引的建议可能对您没有多大帮助。

突出的是关于冗余调用的警告:

OpenGL ES 冗余调用

您不断绑定帧缓冲区并在每一帧设置视口,根据 Time Profiler,这占应用程序工作负载的 10%。注释掉该行

[(EAGLView *)self.view setFramebuffer];

在我的 iPad 2 上,在帧绘制的开始附近导致理论帧速率从 1400 FPS 跃升至 27000 FPS(顺便说一句,您可能应该使用毫秒来测量渲染)。

同样,这是我在 iPad 2 中真正强大的 GPU 上运行的测试,但您应该能够在原始 iPad 或任何其他设备上重复这些类似的步骤,以验证这个性能瓶颈并可能突出其他设备。我发现新的 OpenGL ES Analyzer 在处理与着色器相关的性能问题时非常方便。

于 2011-04-08T15:22:42.720 回答
0

疯狂猜测以下,我没有任何 iPad 经验:

根据这个基准,您可以预期在背景分辨率下纯填充率大约为 214fps。

您是否尝试禁用纹理,以检查您是否受到纹理的限制?

你的纹理是“两个纹理的非幂”吗?在这种情况下,您是否尝试通过替换来删除GL_REPEATfrom ?重复 NPOT 可能会在某些硬件上消耗一些性能。GL_TEXTURE_WRAP_*GL_CLAMP(_TO_EDGE)

最终,您也可以尝试将最小/最大过滤器设置为 GL_NEAREST。

于 2011-04-08T22:51:55.767 回答