IOS OpenGl transparency performance issue
I have built a game in Unity that uses OpenGL ES 1.1 for IOS. I have a nice constant frame rate of 30 until i place a semi transparent texture over the top on my entire scene. I expect the drop in frames is due to the blending overhead with sorting the frame buffer. On 4s and 3gs the frames stay at 30 but on the iPhone 4 the frame rate drops to 15-20. Probably due to the extra pixels in the retina compared to the 3gs and smaller cpu/gpu compared to the 4s. I would like to know if there is anything i can do to try and increase the frame rate when a transparent texture is rendered on top of the entire scene. Please not the the transparent texture overlay is a core part of the game and i can't disable anything else in the scene to speed things up. If its guaranteed to make a difference I guess I can switch to OpenGl ES 2.0 and write the shaders but i would prefer not to as i need to target older devices. I should add that the depth buffer is disabled and I'm blending using SrcAlpha One. Any advice would be highly appreciated. Cheers
I’ve been the graphics performance guy for a few big-name 3D iOS titles, so I completely feel your pain on this one.
My experience has been that transparent pixels are the most expensive thing you can render on modern iOS devices. Your conjecture is right; the greater number of pixels on the iPhone4 really kills its performance in general, and transparent pixels makes it doubly-bad. You’ll find that you have the same problem on the iPad 1, as well.
The particularly slow point is the point where the drawing of a pixel needs to check what the color behind it was. This occurs for transparencies, for alpha masking (“discard” statements in shaders), etc.
In order to deal with this, we took a few steps:
- Wherever possible, we made more draw calls in order to draw more opaque textures. For example, we made tree foliage consist of two parts; the opaque bits in the middle, and the transparent bits around the outside. This meant we drew far more triangles and had to perform more draw calls overall, but it reduced the number of transparent pixels on the screen. Similarly, when we wanted a “vignette” effect which applied a circular darkening around the outside of the screen, we did that by drawing small rectangles with the darkness texture at the edges of the screen, instead of by naively drawing a single full-screen quad that covered the whole screen.
- Wherever possible, we used OpenGLES shaders to render the transparency as part of the fragment shader. So inside the fragment shader it would do normal shader activities, but would also check the fragment’s position on the screen, and figure out any overlay modifiers which needed to be applied.
- We disabled many shaders and transparency effects on iPhone4 and iPad1, judging that they were too expensive for the hardware.
We also tested (but didn’t actually ship with):
- Render into a render target that’s only 3/4 of the full screen resolution, and scale it up for display. This made a huge improvement to performance, but we decided the quality loss was unacceptable for our game.
So there are definitely savings which can be made. But I want to stress that you’re going to have performance problems on the iPhone 4 and the iPad 1 regardless of what you do; their graphic chips simply aren’t fast enough to power their number of pixels, and neither have good shader performance (my tests indicated that their baseline performance running with fixed-function-alike shaders had them running 5-10% slower than they did under the fixed function pipeline). And this was a full-time job for me; if you’re in a smaller team, you may not want to invest your man-months in that way.
As a general rule of thumb, your best bet is to limit overdraw as much as you can, and to try to minimise the number of pixels affected by transparency as much as you can (either by making less stuff transparent, or by moving the transparent stuff further away from the camera, so it’s not covering as many pixels).
And then you have to decide how low you’re willing to go in terms of frame rate on the troublesome iPhone 4 and iPad 1, and start cutting effects in order to meet that target frame rate.
I’m pretty sure you have hit the fillrate limit; since PVR GPUs use a tile-based approach for rendering, drawing transparent parts that affect lots of pixels kills the performance.
Try moving to OES 2 and apply the overlay directly when drawing the geometry, or draw the entire scene to a framebuffer object and blend with your overlay manually. 3GS supports OES 2, and it should be your lowest target device.
I don’t think the problem is the transparency, try using an opaque texture instead and see if there is a difference in performance. I think the problem is that you are maxing the rendering bus bandwidth. See here. Try using pvr-compressed textures.
You should draw transparent primitives after opaque for best performance, because PowerVR GPUs use Tile-Based Deferred Rendering.
- Database Administration Tutorials
- Programming Tutorials & IT News
- Linux & DevOps World
- Entertainment & General News
- Games & eSport