Hey! First of all, sorry for the name of the topic, I have no idea how to call the problem I am having.
First of, here are my shaders because there’s no way you’ll understand without seeing them.
VertexShader:
attribute vec3 a_position; //attributes of vertex
attribute vec3 a_normal;
attribute vec2 a_texCoord0;
uniform mat4 u_worldTrans;
uniform mat4 u_projViewTrans; //some uniforms like transform of model, and camera matrix
uniform vec3 lightPos; //position of light
varying vec3 toCameraVector; //sending a toCameraVector to fragment shader (vector that points to camera)
varying vec2 v_texCoord0; //sending texCoords
varying vec3 normal; // sending Normal of vertex
varying vec3 toLightNormal; //sending toLightVector (vector that points to light)
void main() {
v_texCoord0 = a_texCoord0; //setting texCoords for fragment shader
vec4 worldTrans = u_worldTrans * vec4(a_position, 1.0); //calculate worldTransform of vertex
gl_Position = u_projViewTrans * worldTrans; //setting the position of vertex
normal = (u_worldTrans * vec4(a_normal, 0.0)).xyz; //setting the normal in worldCoords
toLightNormal = lightPos - worldTrans.xyz; // setting toLightVector
toCameraVector = (inverse(u_projViewTrans) * vec4(0.0, 0.0, 0.0, 1.0)).xyz - worldTrans.xyz; //setting toCameraVector
}
FragmentShader:
#ifdef GL_ES
precision mediump float; //have no idea what this does but it is needed I think
#endif
varying vec2 v_texCoord0; //getting all the info from vertexShader like texCoords, normal, and those 2 directional vectors
varying vec3 normal;
varying vec3 toLightNormal;
varying vec3 toCameraVector;
uniform sampler2D grass; //my textures. grass, dirt, path, flowers are than placed onto the mesh depending on the BlendMap color at corresponding pixel
uniform sampler2D dirt;
uniform sampler2D path;
uniform sampler2D flowers;
uniform sampler2D blendMap;
uniform sampler2D pathSpec; // specular map for path texture
uniform vec3 lightColour; //Colour of the light
float damper = 20; // some settings for customizable specular lighting
float reflectivity = 1;
void main() {
vec4 blendMapColour = texture(blendMap, v_texCoord0); //get the color of the blendMap at the corresponding pixel to vector
float grassColour = 1 - (blendMapColour.r + blendMapColour.g + blendMapColour.b); //I want to place grass when there is black color on the BlendMap so I create float that indicates that and then I will multiply grass texture with it.
vec2 texCoord = v_texCoord0 * 40; // multiply texCoords for tiling the texture
vec4 grassC = texture(grass, texCoord) * grassColour; //get all the textures at the corresponding pixel and then I multiply those by a color of the blendMap, basically, if there's black color I want to place grass, if red color I want to place //dirt texture and so on. You know, if there's no red color at the pixel of the Blendmap then the dirtTex.rgba are 0 so there's no dirt texture at all
vec4 dirtC = texture(dirt, texCoord) * blendMapColour.r;
vec4 pathC = texture(path, texCoord) * blendMapColour.b;
vec4 flowersC = texture(flowers, texCoord) * blendMapColour.g;
vec4 pathS = texture(pathSpec, texCoord) * blendMapColour.b;
vec4 finalColor = grassC + dirtC + pathC + flowersC; //mix all the textures together
vec3 UniteNormal = normalize(normal); //here the diffuse lighting calculations starts, no need to comment it I think
vec3 UnitLightNormal = normalize(toLightNormal);
float nDotl = dot(UniteNormal, UnitLightNormal);
float brightness = max(nDotl, 0.2);
vec3 diffuse = lightColour * brightness; //the diffuse lighting calculations ends
if (pathC.r > 0) { //if there is path texture at the corresponding pixel, I want to calculate the specular light of it so I do that here
vec3 UnitCameraVector = normalize(toCameraVector);
vec3 fromLightNormal = -UnitLightNormal;
vec3 reflectedVector = reflect(fromLightNormal, UniteNormal);
float SpecFactor = dot(reflectedVector, UnitCameraVector);
SpecFactor = max(SpecFactor, 0.0);
float Dumped = pow(SpecFactor, damper);
vec3 finalSpec = Dumped * reflectivity * lightColour;
gl_FragColor = vec4(diffuse, 1.0) * finalColor + vec4(finalSpec, 1.0) * pathS.r; // and now just apply the diffuse light, finalColor(which is now the path Texture basically) and specularlight onto the pixel
} else {
gl_FragColor = vec4(diffuse, 1.0) * finalColor; //if there is not path texture at the corresponding pixel but there's grass or whatever else, I dont do specular light.
}
}
Basically, my shaders are pretty advanced(they do diffuse lighting, specular lighting, multitexturing) and I noticed quite bad performance with it. The main problem occured when I wanted to optimize it. I tried to “profile” what slows it all down, so I tried to modify everything and found out that if I pass red(vec4(1,0,0,1)) or any other color to gl_FragColor(the color of pixel), so I dont draw the lighting and textures, everything works pretty good. What a weird thing? I still do all the light and multitexturing calculations in fragment Shader, but I dont draw them and FPS are good. This means, there is not any problem in calculations, but there’s problem in displaying the result. Then I played around with it little more and found out that if I just mix all the textures together(without multiplying them by color of the blendMap) and pass it onto pixel color the performance is still good. but then if I multiply the result with diffuse vec. it starts to be worse and worse.
My question is, is this how it should work? I mean, I could understand that displaying the textures may slow down game, but as I mentioned, this doesn’t…
I really appreciate any advice. Thanks in advance!