Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 10 of 11

Thread: Fps drops when passing multiplied vector to gl_FragColor

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Junior Member Newbie
    Join Date
    Aug 2014
    Posts
    21

    Exclamation Fps drops when passing multiplied vector to gl_FragColor

    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:
    Code :
    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:
    Code :
    #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!

  2. #2
    Intern Newbie
    Join Date
    Sep 2014
    Posts
    30
    Quote Originally Posted by Kalir44 View Post
    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?
    It's called dead code elimination. If calculations have no effect on the final output the compiler simply removes them.

  3. #3
    Junior Member Newbie
    Join Date
    Aug 2014
    Posts
    21
    Thanks for the information

    But, by to "profile" I mean, I just tried different variations of fragment Shader and then had a look at FPS I am getting. I didn't use any profiling tool.
    Last edited by Kalir44; 07-14-2015 at 05:04 AM.

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,574
    It doesn't matter how you measure performance.

    If a calculation has no effect upon the shaders outputs (which can include atomic counters, images, and buffer variables, as well as the shader's "out" variables), the compiler will simply remove it.

  5. #5
    Junior Member Newbie
    Join Date
    Aug 2014
    Posts
    21
    Idk what you mean. The compiler has to do all everything written in code, doesn't it? You probably mean some profile compiler that profiles your game and after that pops you which functions are expensive, but I just did normal "run" function in the IDE and tried different variations of shaderCode to see what works the best

  6. #6
    Junior Member Newbie
    Join Date
    Jun 2014
    Posts
    18
    what GClements means is, your output of the fragment shader is what you set inside gl_FragColor. After all that s what is going to be rendered for that fragment. Now when you do all your calculation and your texturing but that doesnt affect at all the final color you set in the gl_FragColor is like you are not doing anything useful. The compilers are super smart and can see that, and since doesn't contribute in any way to the final computation it just removes that code from the final exectuable. If you ever had a look to assembly code of c++ code you would be much surprised of how much stuff the compiler does and the final code might look so different. You want to do a quick test? Create an attribute in your code, maybe something like attribute vec3 a_position2; and do nothing else, after you compile the shader try to query the location of that attribute, opengl will return a -1, because It cannot find that attribute, it was not used for anything so the compiler just took it away.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •