I have about 30 shaders with high complexity (about 30+ uniforms for each of them). My render loop currently uses only one shader, that I reduced to bare minimum (you are right, uniforms are stripped away during build)
My current shader looks like this:
vec4 CalcAmbientLight(Material mat, float fIntensity)
{
return mat.vAmbient * en_vAmbLightColor * fIntensity;
}
uniform sampler2D normal_buffer;
uniform sampler2D bg_buffer;
uniform vec2 canvasSize;
uniform SpotLight en_spotLight[6];
varying vec2 vTexCoord;
void main()
{
vec4 normalMap = texture2D(normal_buffer, vTexCoord); //normal_buffer is RGBA (GL_RGBA)
vec3 bgColor = texture2D(bg_buffer, vTexCoord).rgb; //bg_buffer is RGB (GL_RGB)
vec3 vNormal = normalize((2.0 * normalMap.rbg) - 1.0);
vec3 posWS = vec3(vTexCoord.x * canvasSize.x, normalMap.a, vTexCoord.y * canvasSize.y);
//----------------------------------------------------------------------------------
Material mat;
mat.vAmbient = vec4(bgColor, 1.0);
mat.vDiffuse = vec4(bgColor, 1.0);
mat.vSpecular = vec4(1.0);
mat.fShiness = 30.0;
vec4 vPhong = CalcAmbientLight(mat, 0.2);
vPhong.a = 1.0;
gl_FragColor = vPhong;
}
Vertex shader is simple pass-through. I am rendering fullscreen quad at resolution of the iPhone4 screen.
With this piece of "nothing" code, I have 45fps (I know it is debug mode, but still it is way to low from 60fps). Same code has 60fps on iPhone5S. CPU is at 4.4ms / frame. GPU takes 20.1ms
Here is also my sequnce of calls from XCode frame trace
//use render to texture for the whole scene
#0 glBindFramebuffer(GL_FRAMEBUFFER, 7)
#1 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 6, 0)
#2 GL_FRAMEBUFFER_COMPLETE <- glCheckFramebufferStatus(GL_FRAMEBUFFER)
#3 glBindRenderbuffer(GL_RENDERBUFFER, 8)
#4 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 8)
#5 GL_FRAMEBUFFER_COMPLETE <- glCheckFramebufferStatus(GL_FRAMEBUFFER)
#6 glUseProgram(17)
#7 glBindTexture(GL_TEXTURE_2D, 3)
#8 glBindVertexArray(1)
#9 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 44)
#10 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)
#11 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
#12 glBindVertexArray(0)
//----------------------------- End of main rendering --------
//now render texture to screen
#13 glBindFramebuffer(GL_FRAMEBUFFER, 1)
#14 glBindRenderbuffer(GL_RENDERBUFFER, 2)
#15 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 2)
#16 GL_FRAMEBUFFER_COMPLETE <- glCheckFramebufferStatus(GL_FRAMEBUFFER)
#17 glBindRenderbuffer(GL_RENDERBUFFER, 1)
#18 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 1)
#19 GL_FRAMEBUFFER_COMPLETE <- glCheckFramebufferStatus(GL_FRAMEBUFFER)
#20 glUseProgram(25)
#21 glBindTexture(GL_TEXTURE_2D, 6)
#22 glBindVertexArray(2)
#23 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 4)
#24 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr)
#25 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
#26 glBindVertexArray(0)
#27 glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, {GL_DEPTH_ATTACHMENT})
#28 glBindRenderbuffer(GL_RENDERBUFFER, 2)
#29 ["Context 1" presentRenderbuffer:GL_RENDERBUFFER]