Game Development Stack Exchange is a question and answer site for professional and independent game developers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have a very simple shader and added linear fog via mix like this:

finalColor = mix(finalColor, vec3(0.5, 0.8, 0.95), vUVoutAndViewZ.z);

Note that the view Z distance is in the variable that also contains the UV coordinates, so the fog didn't even add a new interpolator.

Still, this one innocuous line brought the framerate on the OG Droid with the Power SGX chipset from 33fps to 22fps. Even the HTC Evo with the Adreno 200 GPU stays under 30fps. (The Adreno 205 is at a constant 60fps, but that thing is a beast).

The fragment shader itself is primitive (all values are hard-coded since it's a test shader):

precision mediump float;
varying mediump vec3 vUVoutAndViewZ;
varying lowp vec3 vNormalOut;

uniform lowp sampler2D diffuse;

void main() {
    lowp vec3 normal = vNormalOut;

    // Lighting
    lowp vec3 lightDir = vec3(0.5, 0.3, 0.5);
    lowp vec3 light = vec3(dot(normal, lightDir));

    lowp vec3 diffuse = texture2D(diffuse, vUVoutAndViewZ.xy).rgb;

    lowp vec3 finalColor = diffuse * light;

    // Fog
    finalColor = mix(finalColor, vec3(0.5, 0.8, 0.95), vUVoutAndViewZ.z);

    gl_FragColor = vec4(, 1.0);

I added the lowp/mediump declarations later (which added about 2fps), it works just as bad without them.

I refuse to believe that the PowerVR chipset is so weak that it can't handle a simple shader like this. There must be something stupid in this shader (like something implicitly swizzling a lowp register) that just completely messes up the unit.


Ellis has some fantastic information in the answer and the subsequent comments. In this particular case, it seems that mix() is flat-out broken. It brought the shader to 12 cycles (from 4) and 4 GPRs (from 2). I got back to 29fps by using this code instead:

lowp vec3 fogDiff = vec3(0.5, 0.8, 0.95) - finalColor;
fogDiff *= vUVoutAndViewZ.z;
finalColor += fogDiff;
share|improve this question
Do you know that fog is not linear with depth? If you are not afraid of adding pow function to the shader, i think you should try to make it more realistic ;) – Notabene Apr 20 '11 at 12:23
@notabene: I'm aware of that, but since this post is about how a simple mix() killed the framerate, I wasn't too inclined to throw in a pow to finish it off. – EboMike Apr 20 '11 at 15:34
up vote 5 down vote accepted

Response from EboMike computed with PVRUniSCo Editor: mix() brings the shader from 4 cycles to 12 cycles (PowerVR).

The PowerVR 530/535 is very slow. Andreno 200 and PowerVR 530/535 are first GPU generation (OpenGL ES 2.x) for hdpi resolution. You can't redraw a full screen at 60FPS with a simple texture.

I wrote GPUBench to test shaders performance and it is very bad on these GPU. The second generation (Andreno 205, Powervr 540) is far better.

Today, i try to minimize Fragment shader with one or two operations. You can try to optimize your shader because GLSL compilers are bad (on mobile platform).

Note: for powervr gpu, read this document. PVRUniSCo Editor can compute cycles used in shaders.

My toughts:

  • The Droid GPU is slower than Andreno 200 because of fillrate
  • 30 FPS for Andreno 200 is good
  • 20 FPS for Droid is good
  • You can render your scene in a smaller FBO and draw it on a screen (but FBO switch is costly)
  • Fragment shaders must be very short.
share|improve this answer
You're breaking my heart! What about the HTC Evo? Wouldn't the Adreno 200 at least be able to handle that? Even for a weak GPU, that seems unreasonably pathetic. – EboMike Apr 20 '11 at 5:49
My goal is 30fps at least for the Droid and EVO. I vaguely remember games like Backbreaker that SEEM to look quite nice (been a while since I've seen it, I might be wrong). What's the secret here? I have no overdraw, I barely use alpha blending, and this shader is primitive. Do you have any idea? (Btw, will accept answer in a few hours, don't worry :) ) – EboMike Apr 20 '11 at 5:53
30 FPS for Droid or EVO is very difficult. These GPU have very low fillrate. – Ellis Apr 20 '11 at 6:01
I don't know anything about mobile graphics chipsets, but I can't help noticing that you didn't explain the most interesting part. Why a single line drops performance so dramatically? Is it really slow mix operation? – Nevermind Apr 20 '11 at 7:17
I haven't tried it but you can look "PVRUniSCo Editor" for GLSL instruction cycles. – Ellis Apr 20 '11 at 7:34

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.