混合大型四核的性能受到影响

时间:2011-11-20 23:35:03

标签: iphone ios opengl-es

我有一个在视网膜显示器上运行得很好(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;

4 个答案:

答案 0 :(得分:3)

好的,我认为你已经遇到了硬件的限制。在整个场景中混合屏幕大小的四边形对于基于图块的硬件来说可能是特别糟糕的情况。 PowerVR SGX(在iPhone上)针对隐藏表面移除进行了优化,以避免在不需要时进行绘制。它具有低内存带宽,因为它针对低功耗设备进行了优化。

因此屏幕大小的混合四元组正在读取然后在屏幕上写入每个片段。哎哟!

glClear加速是相关的 - 因为你告诉GL你在渲染之前不关心后备缓冲区的内容,这样就可以将以前的内容加载到内存中。

这里有一个非常好的iOS硬件概述:http://www.imgtec.com/factsheets/SDK/POWERVR%20SGX.OpenGL%20ES%202.0%20Application%20Development%20Recommendations.1.1f.External.pdf

至于实际解决方案 - 我会尝试直接在游戏场景中渲染叠加层。

例如,渲染循环应如下所示:

[EAGLContext setCurrentContext:context];

// Set up game view port and render the game
InitGameViewPort();
GameRender();

// Change camera to 2d/orthographic, turn off depth write and compare
InitOverlayViewPort()

// Render overlay into same buffer 
OverlayRender()

答案 1 :(得分:1)

如果渲染到PowerVR芯片上的渲染目标,切换到另一个渲染目标并渲染,然后切换回任何以前的渲染目标,您将遭受重大性能影响。这种访问模式被最新仪器中内置的OpenGL ES Analyzer标记为“逻辑缓冲区加载”。

如果您切换渲染顺序以便首先绘制光照贴图渲染目标,然后将场景渲染到主帧缓冲区,然后执行光照贴图渲染目标纹理的全屏混合,则性能应该更高。

答案 2 :(得分:0)

我可以在iPad 1上使用iOS 4.2确认启用/禁用GL_BLEND,以便在18到31 fps之间切换一个全屏四边形。在两次运行中,渲染器利用率为90-100%。

答案 3 :(得分:0)

即使在摆弄纹理之前,也要确保优化了着色器。填充960x640屏幕(614400像素)时,片段着色器中的任何操作都会产生巨大影响。

为此情况创建特定版本的片段着色器是一件好事。它应该是这样的:

varying mediump vec2 vertexTexCoord;
uniform sampler2D texture;

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

使用此片段着色器创建另一个程序,并在绘制大四边形之前使用它,然后恢复正常程序。 iPhone 4能够通过混合渲染每帧大约7个全屏,1:1纹理四边形,但使用更复杂的着色器可快速降至约1个。

(另外在你的情况下,尝试首先渲染覆盖纹理,然后渲染普通元素,然后渲染其余纹理。它应该显着提高性能。)