glDrawArrays 上的 OpenGL ES 2.0 FPS 严重下降
我正在使用一个简单的 OpenGL ES 2.0 应用程序,更具体地说,我正在使用 GLWallpaperService 制作动态壁纸。感谢 StackOverflow 社区的大量帮助(谢谢大家!),我已经设法找到了一个很好的方法,但我似乎遇到了一些性能问题,尽管它仍然非常简单。
现在,就绘图而言,我只在屏幕上绘制四个三角形条并为每个三角形条应用纹理。虽然我确信这并不理想,但我认为通过四次单独调用 glDrawArrays 来完成此操作会很好,但显然这个操作比我想象的要繁重得多。仅这四个绘制调用似乎就将 Droid X 上壁纸的 FPS 削减了一半以上,从 60 下降到 20 左右。
虽然出于明显的原因我不想以最大 FPS 渲染壁纸,但在我只绘制四个三角形条带的早期阶段出现这种极端下降是不可接受的。在最终版本中,将会有更多的绘图进行,包括粒子系统,在我控制住我的表现之前我无法继续。
我还没有深入研究 VBO,因为我认为我还不需要这样做,但它们听起来像是我在这种情况下应该追求的。即使对于如此简单的绘制调用,它们真的需要吗?我不久前还读到,他们在某些手机上存在问题,但我相信这仅适用于较旧的手机,这不适用于我,因为我需要 OpenGL ES 2.0 以及动态壁纸支持。
另外,在这里偷偷提出另一个问题,我无法启用调试来查看我的壁纸到底发生了什么。我的清单设置正确,经过快速搜索后,我添加了以下行:
android.os.Debug.waitForDebugger();
到我的代码中,但它永远不会附加,只是在等待时将我的壁纸保留为黑色(永远)。当监控性能对于动态壁纸之类的东西如此重要时,这肯定是一个问题,因此对于对此的任何见解也给予奖励。
编辑::这是我当前的片段着色器。这是相当拼凑在一起的,只是为了暂时让事情正常工作,并且存在一些与我的应用程序其他部分相关的错误,但我不认为它会导致我的问题。
final String fragmentShader =
"precision mediump float; \n"
+ "varying vec2 v_Color; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform vec4 u_Color; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor = texture2D( s_baseMap, v_Color ); \n"
+ " vec4 colorAdd1 = vec4(u_Color); \n"
+ " if(baseColor.a > 0.0){ \n"
+ " if(baseColor.a < 0.5){ \n"
+ " baseColor.a = 0.0; \n"
+ " } else { \n"
+ " baseColor = (baseColor + colorAdd1); \n"
+ " } \n"
+ " } \n"
+ " gl_FragColor = baseColor; \n"
+ "} \n";
我以编程方式“着色”我的纹理以实现自定义目的,这就是“u_Color”向量所代表的内容。检查纹理 Alpha 的麻烦在于防止它只将颜色应用于每个像素,并且只在“实体”像素上进行。我确实删除了该部分一次来查看 FPS 的结果,虽然它确实增加了,但似乎只增加了 3-5FPS 的一小部分。
编辑:: 我只是通过日志消息进行了一些测试,似乎我的“onDraw”方法中没有任何内容造成了我的问题。如果我在 onDraw 方法的最开始记录一些内容,然后在完成所有绘图和所有内容之后在最后记录其他内容,那么它们每次几乎都会同时记录,当然不足以导致我遇到的巨大差距。除非这是日志系统的一些错误,否则我必须在其他地方得到这些帧速率的滞后。
以我目前对 OpenGL ES 2.0 的了解,这对我来说似乎相当令人困惑。我被引导相信,一旦它到达 onDraw 方法,它就会像循环一样在该方法中持续运行,直到某些状态发生变化,例如更改方向和调用 onSurfaceChanged。如果我上面描述的不是 logcat 处理事情的方式中的错误,那么它必须离开这个循环并转到让我陷入困境的地方。
我能想到的唯一解释是,我为了在动态壁纸中使用 OpenGL ES 2.0 而使用的 GLWallpaperService 设置是罪魁祸首。不幸的是,除非我可以对此进行调试以准确显示速度变慢的位置,否则我不确定如何找到并(希望)修复它,因此似乎无法使用调试工具对我来说是最大的问题。
I am working with a simple OpenGL ES 2.0 app, more specifically I am working on a live wallpaper utilizing GLWallpaperService. I've managed to get a good ways into it thanks to a lot of help from the StackOverflow community (Thanks guys!), but I seem to be running into a bit of a performance issue even though it is still very simplistic.
Right now, as far as drawing goes, I am only drawing four triangle strips to the screen and applying a texture to each. While I'm sure it is not ideal, I figured it would be fine to do this with four separate calls to glDrawArrays, but apparently this operation is much more taxing than I imagined. Those four draw calls alone seem to be cutting the FPS of my wallpaper on my Droid X by over half, from 60 down to the mid 20's.
While I don't want to me rendering a wallpaper at max FPS for obvious reasons, having this extreme drop in this early stage when I am only drawing four triangle strips is unacceptable. There will be quite a bit more drawing going on, including a particle system, in the final version and I cannot move on until I have my performance under control.
I have not looked into VBO's very much as I didn't think I needed to yet, but they sound like what I should be going for in this situation. Are they really required even for such simple draw calls? I also read a while back that they have issues with certain phones, but I believe this only applied to older phones, which doesn't apply to me since I will require OpenGL ES 2.0 as well as Live Wallpaper support.
Also, to sneak another question in here, I am unable to enable debugging in order to see what exactly is happening with my wallpaper. My manifest is set properly, and after a quick search I added the line :
android.os.Debug.waitForDebugger();
To my code, but it will never attach and simply leave my wallpaper black while it waits (forever). This is certainly a bit of a problem when monitoring performance is so essential for things like live wallpapers, so bonus kudos for any insight on this one as well.
EDIT :: Here is my current fragment shader. This is pretty cobbled together, just to make things work for the time being, and has some bugs relating to other parts of my app, but I don't see it causing my issues.
final String fragmentShader =
"precision mediump float; \n"
+ "varying vec2 v_Color; \n"
+ "uniform sampler2D s_baseMap; \n"
+ "uniform vec4 u_Color; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 baseColor = texture2D( s_baseMap, v_Color ); \n"
+ " vec4 colorAdd1 = vec4(u_Color); \n"
+ " if(baseColor.a > 0.0){ \n"
+ " if(baseColor.a < 0.5){ \n"
+ " baseColor.a = 0.0; \n"
+ " } else { \n"
+ " baseColor = (baseColor + colorAdd1); \n"
+ " } \n"
+ " } \n"
+ " gl_FragColor = baseColor; \n"
+ "} \n";
I am "colorizing" my textures programatically for customization purposes, which is what the "u_Color" vector represents. The mess about checking the textures alpha is to prevent it from just applying the color to every pixel and only doing it on the 'solid' ones. I did remove that part once to see the result to my FPS, and while it did indeed increase, it was only seemed to be by a small amount of 3-5FPS.
EDIT :: I was just doing a little testing via log messages and it seems as though nothing in my "onDraw" method is creating my problem. If I log something at the very beginning of my onDraw method, and then something else at the very end after all of my drawing and everything, they both log almost instantaneously every time, certainly not enough to cause the huge gaps I am experiencing. Unless this is some fault of the log system, then I have to be getting these lags in framerate elsewhere.
With my current knowledge of OpenGL ES 2.0, this seems quite baffling to me. I was lead to believe that once it got around to the onDraw method, it would continuously run in that method like a loop up until some state change, such as changing orientation and calling onSurfaceChanged. If what I described above is not a bug in the way the logcat handles things, then it must leave this loop and go somewhere that is bogging me down.
The only explanation I can think of for this is that the GLWallpaperService setup that I am using in order to use OpenGL ES 2.0 in live wallpapers is to blame. Unfortunately, unless I can get debug working on this to show me exactly where the slow down is happening, I am not sure how I would be able to find and (hopefully) fix it, so it seems not being able to use the debugging tools is the biggest problem for me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,OpenGL ES 需要 VBO/VAO,因为此版本 (glBegin/End) 不再支持固定功能。
如果没有代码,很难说问题出在哪里。但事情绝对不应该这样。 (我没有安卓手机)
但我可以发布一些链接...
http://www.songho.ca/opengl/gl_vbo.html(我更喜欢这个)
http://www.songho.ca/opengl/gl_vertexarray.html(您也可以试试这个)
Yes, VBOs/VAOs are required for OpenGL ES as the fixed function stuff is not supported anymore in this version (glBegin/End).
Hard to say where the problem is, without some code. But it certainly shouldn't be that way. (I have no android phone)
But i can post some links...
http://www.songho.ca/opengl/gl_vbo.html (i prefer this)
http://www.songho.ca/opengl/gl_vertexarray.html (you can also try this)
除非您正在绘制一些非常大的顶点数组,否则 glDrawArray 调用可能不是问题。问题更有可能是您与 glDrawArray 一起进行的调用,或者是片段着色器中发生的情况。例如,如果您通过 2048x2048 纹理的混合和采样来填充整个屏幕 4 次,或者每次都重新编译着色器,则预计帧率会下降至 20 fps。
Unless you're drawing some very large vertex arrays, the glDrawArray call probably isn't the problem. The problem is more likely either the calls you're making alongside glDrawArray, or what's happening in your fragment shader. For example, if you're filling the entire screen 4 times with blending and sampling from 2048x2048 textures, or if you're recompiling your shaders every time, a drop to 20 fps would be expected.