I'm trying to make a 3D game for mobile. When rendering a very simple scene, my performance drops from 60 fps to 30 fps when I use fragment shader lighting instead of vertex shader lighting.
I really hate the look of the vertex shader lighting, but I'm worried about whether or not I'm going to be able to run any game system and still get a reasonable framerate if I go with fragment shader lighting. I would like to seek advice as to what should I choose, or if there's any optimisation I could make to a shader to keep the good look and the framerate.
Here's my shader code (I'm using GLSLes 3.0):
vertex shader
#version 300 es
in mediump vec4 position;
in mediump vec2 i_UV;
in mediump vec4 i_Normal;
out mediump vec2 UV;
out mediump vec3 Position;
out mediump vec3 Normal;
out mediump vec3 CamDir;
out mediump float fogFactor;
uniform mat4 transformationMatrix;
uniform mat4 rotationMatrix;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mediump float IOR;
uniform mediump float roughness;
uniform mediump float specular;
out mediump float Fresnel_O;
void main(){
UV = i_UV;
Position = (transformationMatrix*position).xyz;
Normal = normalize((rotationMatrix*i_Normal).xyz);
CamDir = normalize((inverse(viewMatrix) * vec4(0,0,0,1.0)).xyz - position.xyz);
fogFactor = exp(-pow(distance((viewMatrix*transformationMatrix*position).xyz,vec3(0.0,0.0,0.0))*0.01,2.0));
mat4 a = viewMatrix;
//Fresnel
float F_I = -1.0/IOR;
float F_A = dot(refract(CamDir,Normal,F_I),Normal);
float F_B = dot(Normal,CamDir);
Fresnel_O = pow((F_B*F_I-F_A)/(F_B*F_I+F_A),2.0) * (1.0-roughness);
vec4 finalPos = projectionMatrix*viewMatrix*transformationMatrix * position;
gl_Position = finalPos;
}
fragment shader
#version 300 es
precision mediump float;
out highp vec4 Fragment;
in mediump vec2 UV;
in mediump vec3 Position;
in mediump vec3 Normal;
in mediump vec3 CamDir;
in mediump float fogFactor;
const lowp int NUMBER_OF_LIGHTS = 10;
in mediump float Fresnel_O;
uniform mediump vec3 LightPos[NUMBER_OF_LIGHTS];
uniform mediump vec3 LightColor[NUMBER_OF_LIGHTS];
uniform mediump float LightIntensity[NUMBER_OF_LIGHTS];
uniform mediump float roughness;
uniform mediump float Metaliness;
uniform mediump float specular;
uniform mediump sampler2D textureSampler;
uniform mediump vec3 emission;
const mediump vec3 envColor = vec3(0.0,0.1,0.1) * 0.0;
void main(){
vec4 albedo = texture(textureSampler,UV) * color;
if(texture(textureSampler,UV).a < 0.5){ discard; }
vec3 diffColorMultiplier = vec3(0.0);
vec3 specColor = vec3(0.0);
for(int i = 0; i < NUMBER_OF_LIGHTS && LightPos[i] != vec3(0.0); i++){
mediump float LightDist = length(LightPos[i]-Position);
mediump vec3 LightDir = (LightPos[i] - Position)/LightDist;
//diffuse
float diffLightAmount = max(dot(normalize(LightDir), Normal), 0.0);
diffColorMultiplier += LightColor[i]*((diffLightAmount/(LightDist*LightDist))*LightIntensity[i]);
//specular
//custom specular algorythim based on phong shading. It gives me the look I want.
float specularAmount = ((pow(max(dot(reflect(-normalize(LightDir), Normal), CamDir), 0.0), (1.0-roughness)*(1.0-roughness)*300.0) + diffLightAmount*0.01)/(LightDist*LightDist))*Fresnel_O*(LightIntensity[i]*LightIntensity[i]) * specular;
specularAmount = max(specularAmount, 0.0);
specColor += LightColor[i] * specularAmount;
}
vec4 finalColor = vec4(mix(mix((albedo.rgb * diffColorMultiplier) + specColor,specColor,Metaliness)+envColor+emission,envColor,1.0-fogFactor),albedo.a);
Fragment = finalColor;
}
```