我对在OpenGL中使用纹理三角形网格绘制全屏幕背景时看到的糟糕表现感到非常困惑:只使用最基本的着色器绘制背景而没有其他任何东西以40 fps最大化,并且50 fps使用默认管道。
虽然40 fps似乎并不太糟糕,但在其上添加任何其他内容会使fps下降,并且考虑到我需要在其上绘制100-200个其他网格,我最终得到了一个微不足道的15 fps根本不可用。
我已将相关代码隔离到可用的XCode项目here中,但其本质是规范纹理贴图示例:
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纹理映射网格覆盖整个屏幕似乎不可能。
然而,有数百款游戏可以做到这一点,所以它有可能而且我必须做错事,但它是什么?
答案 0 :(得分:7)
不幸的是,我所拥有的只是我的iPad 2来测试它(我的iPad 1测试单元坐在家里),并且它具有可笑的快速片段处理。它被固定在60 FPS,你的日志记录中有1400理论FPS。
然而,我使用OpenGL ES驱动程序和Time Profiler仪器以及酷炫的新OpenGL ES Analyzer(随Xcode 4附带)运行仪器。这就是OpenGL ES Analyzer的结果:
查看OpenGL ES驱动程序中的Tiler Utilization统计信息显示该窗口器几乎没有使用,但渲染器有一些用处(同样,我的iPad 2只有5%)。这表明对几何体使用VBO和索引的建议可能对您没有多大帮助。
突出的是关于冗余呼叫的警告:
您继续绑定帧缓冲区并每帧设置视口,根据Time Profiler,它占应用程序工作负载的10%。评论该行
[(EAGLView *)self.view setFramebuffer];
在你的框架绘图开始附近的导致理论帧率在我的iPad 2上从1400 FPS跳到27000 FPS(另外,你应该measure using milliseconds for your rendering)。
同样,这是我在iPad 2中真正强大的GPU上运行测试,但您应该能够在原始iPad或任何其他设备上重复这些类似步骤,以验证此性能瓶颈并可能突出显示其他设备。我发现新的OpenGL ES Analyzer在获取与着色器相关的性能问题时非常方便。
答案 1 :(得分:0)
狂野猜测,我没有任何iPad体验:
根据此benchmark,您可以预期在背景分辨率下纯填充率大约为214fps。
您是否尝试禁用纹理,检查是否受纹理限制?
你的纹理是否是“两种纹理的无力”?在这种情况下,您是否尝试将GL_REPEAT
从GL_TEXTURE_WRAP_*
移除,替换为GL_CLAMP(_TO_EDGE)
?重复NPOT可能会在某些硬件上花费一些性能。
最终,您可以尝试将最小/最大过滤器设置为GL_NEAREST。