我正在使用OpenGL编写一个2D游戏,但在渲染覆盖整个窗口的一些纹理时遇到了性能问题。
我的做法是创建一个与屏幕大小相同的纹理,使用FBO将场景渲染到该纹理上,然后使用不同的偏移量多次渲染该纹理以获得一种“阴影”效果。但是当我使用集成显卡时,性能会大幅下降。
总体而言,我在整个屏幕上渲染了7个四边形(背景图像、带有黑色“着色”的5个“阴影图像”和相同的真彩纹理)。我使用大小为1024x1024的RGBA纹理,并将其适应于900x700的窗口。当我不渲染纹理时,我可以获得200帧/秒,而当我渲染纹理时,无论是哪种情况,都只有34帧/秒(实际上我都会创建纹理并将场景渲染到其中)。我认为这很奇怪,因为本质上我只渲染了7个四边形。另一个奇怪的事情是,当我运行CPU分析器时,它并没有表明这是瓶颈(我知道OpenGL使用了管道架构,这种情况可能会发生,但大多数情况下却不会)。
当我使用外部显卡时,上述测试结果始终为200帧/秒。但是当我禁用将场景渲染到纹理并禁用将纹理渲染到屏幕上时,我可以获得约1000帧/秒。这仅适用于我的外部显卡-当我使用集成显卡禁用FBO时,我也只能获得相同的200帧/秒。这让我感到非常困惑。
有谁能解释一下发生了什么,并且上述数字是否正确?
集成显卡-Intel HD Graphics 4000
外部显卡-NVIDIA GeForce GTX 660M
P.S.我使用C#编写我的游戏-因此如果那有任何帮助,我使用OpenTK。
编辑:
首先感谢所有回复-它们都在某种程度上非常有帮助,但遗憾的是,我认为简化/优化代码还需要更多的工作。让我分享一些我的渲染代码:
//fields defined when the program is initialized
Rectangle viewport;
//Texture with the size of the viewport
Texture fboTexture;
FBO fbo;
//called every frame
public void Render()
{
//bind the texture to the fbo
GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo.handle);
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, fboTexture,
TextureTarget.Texture2D, texture.TextureID, level: 0);
//Begin rendering in Ortho 2D space
GL.MatrixMode(MatrixMode.Projection);
GL.PushMatrix();
GL.LoadIdentity();
GL.Ortho(viewport.Left, viewport.Right, viewport.Top, viewport.Bottom, -1.0, 1.0);
GL.MatrixMode(MatrixMode.Modelview);
GL.PushMatrix();
GL.LoadIdentity();
GL.PushAttrib(AttribMask.ViewportBit);
GL.Viewport(viewport);
//Render the scene - this is really simple I render some quads using shaders
RenderScene();
//Back to Perspective
GL.PopAttrib(); // pop viewport
GL.MatrixMode(MatrixMode.Projection);
GL.PopMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.PopMatrix();
//Detach the texture
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, fboTexture, 0,
0, level: 0);
//Unbind the fbo
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
GL.PushMatrix();
GL.Color4(Color.Black.WithAlpha(128)); //Sets the color to (0,0,0,128) in a RGBA format
for (int i = 0; i < 5; i++)
{
GL.Translate(-1, -1, 0);
//Simple Draw method which binds the texture and draws a quad at (0;0) with
//its size
fboTexture.Draw();
}
GL.PopMatrix();
GL.Color4(Color.White);
fboTexture.Draw();
}
所以我认为fbo和渲染到纹理并没有问题,因为这不会导致我的两张卡都变慢。以前我每帧都初始化fbo,这可能是我的Nvidia卡变慢的原因,但现在当我预先初始化所有内容时,我得到了相同的FPS,无论是否使用fbo。
我认为问题不在于纹理,因为如果我禁用纹理,只渲染未经纹理处理的四边形,我会得到相同的结果。而且我仍然认为,即使它们覆盖整个屏幕,我的集成显卡在仅渲染7个四边形时也应该运行得更快,甚至快过40 FPS。
你能给我一些提示,如何实际分析这个问题并返回结果吗?那将非常有用。
好的,我进行了一些实验,并取得了更好的性能。首先我尝试使用着色器渲染最终的四边形-这对性能没有影响,正如我所预期的那样。
然后我尝试运行分析器。但据我所知,SlimTune只是一个CPU分析器,它没有给我想要的结果。然后我尝试使用gDEBugger。它与Visual Studio集成,后来我发现它不支持.NET项目。我尝试运行外部版本,但似乎没有起作用(也许我还没有充分使用)。
真正起作用的是,而不是直接将7个四边形渲染到屏幕上,我首先将它们渲染到纹理上,再次使用fbo,然后一次将最终纹理渲染到屏幕上。这使我的fps从40提高到了120。同样,这似乎非常奇怪。为什么渲染到纹理比直接渲染到屏幕要快得多?无论如何,感谢大家的帮助-看来我已经解决了我的问题。如果有人能对这种情况提出合理的解释,我将不胜感激。
GL.MatrixMode(MatrixMode.Projection);
这样的方法,因为太多人使用了固定功能管线。 - Felix K.