Eu tenho um shader muito simples e adicionei nevoeiro linear via mix como este:
finalColor = mix(finalColor, vec3(0.5, 0.8, 0.95), vUVoutAndViewZ.z);
Observe que a distância Z da vista está na variável que também contém as coordenadas UV, portanto o nevoeiro nem adicionou um novo interpolador.
Ainda assim, essa linha inócua trouxe a taxa de quadros no OG Droid com o chipset Power SGX de 33fps para 22fps. Até o HTC Evo com a GPU Adreno 200 fica abaixo de 30fps. (O Adreno 205 está a 60fps constantes, mas isso é uma besta).
O próprio shader de fragmento é primitivo (todos os valores são codificados permanentemente, pois é um shader de teste):
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(finalColor.xyz, 1.0);
}
Eu adicionei as declarações lowp / mediump mais tarde (que adicionaram cerca de 2fps), funciona tão ruim sem elas.
Recuso-me a acreditar que o chipset PowerVR é tão fraco que não consegue lidar com um shader simples como esse. Deve haver algo estúpido nesse sombreador (como algo implicitamente mexendo em um registro lowp) que apenas atrapalha completamente a unidade.
RESPOSTA e EDIÇÃO:
Ellis tem algumas informações fantásticas na resposta e nos comentários subsequentes. Nesse caso em particular, parece que mix () é totalmente quebrado. Ele trouxe o sombreador para 12 ciclos (de 4) e 4 GPRs (de 2). Voltei a 29fps usando este código:
lowp vec3 fogDiff = vec3(0.5, 0.8, 0.95) - finalColor;
fogDiff *= vUVoutAndViewZ.z;
finalColor += fogDiff;
mix()
matou a taxa de quadros, eu não estava muito inclinado a fazer um pow
para acabar com isso.