【发布时间】:2011-11-20 23:35:03
【问题描述】:
我有一款在视网膜显示器上运行良好 (55-60fps) 的游戏。 我想添加一个与现有场景融合的全屏覆盖。但是,即使使用较小的纹理,对性能的影响也是巨大的。我可以进行优化以使其可用吗?
如果我使用 80x120 纹理(纹理是动态渲染的,这就是它不是方形的原因),我会得到 25-30FPS。如果我使纹理更小,性能会提高,但质量是不可接受的。不过,一般来说,叠加层的质量并不是很重要(它只是照明)。
渲染器利用率为 99%。
即使我使用文件 (.png) 中的方形纹理,性能也很差。
这就是我创建纹理的方式:
[EAGLContext setCurrentContext:context];
// Create default framebuffer object.
glGenFramebuffers(1, &lightFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer);
// Create color render buffer and allocate backing store.
glGenRenderbuffers(1, &lightRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, LIGHT_WIDTH, LIGHT_HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, lightRenderbuffer);
glGenTextures(1, &lightImage);
glBindTexture(GL_TEXTURE_2D, lightImage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LIGHT_WIDTH, LIGHT_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, lightImage, 0);
这里是渲染...
/* Draw scene... */
glBlendFunc(GL_ONE, GL_ONE);
//Switch to offscreen texture buffer
glBindFramebuffer(GL_FRAMEBUFFER, lightFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, lightRenderbuffer);
glViewport(0, 0, LIGHT_WIDTH, LIGHT_HEIGHT);
glClearColor(ambientLight, ambientLight, ambientLight, ambientLight);
glClear(GL_COLOR_BUFFER_BIT);
/* Draw lights to texture... */
//Switch back to main frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glViewport(0, 0, framebufferWidth, framebufferHeight);
glBlendFunc(GL_DST_COLOR, GL_ZERO);
glBindTexture(GL_TEXTURE_2D, glview.lightImage);
/* Set up drawing... */
glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, 0);
以下是我在尝试缩小问题范围时采用的一些基准。 “无混合”意味着我在绘制四边形之前 glDisable(GL_BLEND)。 “无缓冲区切换”意味着我在绘制之前不会从屏幕外缓冲区来回切换。
(Tests using a static 256x256 .png)
No blend, No buffer switching: 52FPS
Yes blend, No buffer switching: 29FPS //disabled the glClear, which would artificially speed up the rendering
No blend, Yes buffer switching: 29FPS
Yes blend, Yes buffer switching: 27FPS
Yes buffer switching, No drawing: 46FPS
感谢任何帮助。谢谢!
更新
我没有在之后混合整个光照贴图,而是最终编写了一个着色器来动态完成这项工作。每个片段都从光照贴图中进行采样和混合(有点像多重纹理)。起初,性能提升很小,但后来我为光照贴图使用了 lowp sampler2d,然后我得到了大约 45FPS。
这是片段着色器:
lowp vec4 texColor = texture2D(tex, texCoordsVarying);
lowp vec4 lightColor = texture2D(lightMap, worldPosVarying);
lightColor.rgb *= lightColor.a;
lightColor.a = 1.0;
gl_FragColor = texColor * color * lightColor;
【问题讨论】:
-
我怀疑
glView缓冲开关可能是这里的罪魁祸首。这些方法发生了什么?为什么不使用glBindRenderBuffer? -
我将内联这些方法以进行澄清。
-
可以调试性能问题,尝试预渲染叠加层(暂时保持静态),然后每帧将其复制到主缓冲区。这至少会告诉你缓冲区切换是否很慢(即每帧对 glBindFrame、glBindRender、glViewport 进行两次调用)。
-
如果我只做绘图以外的所有事情(包括 BindRender、Viewport 的东西和实际绘制灯光),它会很快。所以我认为它必须是缓慢的最终绘图/合成。
-
如果你这样做
glDisable(GL_BLEND)会加快速度吗?