Lighting ring artifact!

Recently I am working on SpotLight implementation and I found this ring artifact (a circular ring around the light source) issue.

Here is my fragment shader:

#version 330 core                                
in vec3 v_Position;        // Interpolated position for this fragment.
//in vec4 v_Color;              // This is the color from the vertex shader interpolated across the
                                  // triangle per fragment.
in vec3 v_Normal;             // Interpolated normal for this fragment.


in vec3 v_OriginalPosition;        // This will be passed into the fragment shader.
in vec3 v_CubeOriginalPosition;
in vec2 UV;
in vec4 ShadowCoord;


uniform sampler2D myTextureSampler;
uniform sampler2D shadowMap;
//uniform sampler2DShadow shadowMap;
uniform samplerCube skybox;


uniform vec3 camPos;


uniform vec3 shadowVect;
uniform vec4 LineColor;


uniform int bShadowOn;
uniform int bTextureOn;


uniform mat4 u_MVPMatrix;        // A constant representing the combined model/view/projection matrix.


// Ouput data
out vec4 color;


uniform float transparent;
uniform float Materialshininess;


uniform int CubeMapReflection;


uniform int IsOrthographic;


const int MAX_LIGHTS = 10;
uniform int numLights;


struct Light {
   vec3 position;
   vec4 diffuse;
   vec4 ambient;
   vec4 specular;


   int spotLight;
   vec3 spotDirection;
   float spotCosCutoff;
   float spotExponent;
   float constantAttenuation;
   float linearAttenuation;
   float quadraticAttenuation;
};


uniform Light allLights[MAX_LIGHTS];




vec4 ApplyLight(Light light){


    // Get a lighting direction vector from the light to the vertex.
    vec3 lightVector;


float att=1;
if(light.spotLight==1){


        vec3 vertexToLightSource =vec3(light.position - v_OriginalPosition);


        // Will be used for attenuation.
        float distance = length(vertexToLightSource);
        lightVector = normalize(vertexToLightSource);


        float spotEffect = dot( normalize(-lightVector),normalize( light.spotDirection));
        if (spotEffect > light.spotCosCutoff) {
            spotEffect = pow(spotEffect, light.spotExponent);
            att = spotEffect / (light.constantAttenuation +
                    light.linearAttenuation * distance +
                    light.quadraticAttenuation * distance* distance);             
        }
        else {
             att=0.0;
        }
}
else {
       lightVector = normalize(light.position);    
}   

    vec3 E = normalize(v_OriginalPosition-camPos); // we are in Eye Coordinates, so EyePos is (0,0,0)  
    vec3 R= normalize(reflect(-lightVector , v_Normal) );  


   // calculate Specular Term:
   vec4 Ispec = light.specular * pow(max(dot(R,E),0.0),Materialshininess);                
   Ispec = clamp(Ispec, 0.0, 1.0);  


    // Calculate the dot product of the light vector and vertex normal. If the normal and light vector are
    // pointing in the same direction then it will get max illumination.
    float diffuse;


    if (gl_FrontFacing) {
            diffuse = max(dot(v_Normal, lightVector), 0.0);
        } 
       else {
             diffuse = max(dot(-v_Normal, lightVector), 0.0);
        }




    return att * ((light.diffuse * diffuse) + light.ambient + Ispec) ;
}


// The entry point for our fragment shader.
void main()
{
  vec4 linearColor = vec4(1,1,1,1);
   
  if(bTextureOn==1){
   // Material properties
       vec3 MaterialDiffuseColor = texture( myTextureSampler, UV ).rgb;
           linearColor = vec4(MaterialDiffuseColor,1);
   }
   else if(bTextureOn==2){
       if(CubeMapReflection==0){
           vec4 MaterialDiffuseColor = texture( skybox, v_CubeOriginalPosition);
               linearColor = vec4(MaterialDiffuseColor);
           }
       else {
                float ratio = 1.00 / 1.52;
                vec3 I = normalize(v_CubeOriginalPosition - camPos);
                vec3 R = reflect(I, normalize(v_Normal));
                linearColor = vec4(texture(skybox, R).rgb, 1.0);
       }
   }   


  vec4 tempColor=vec4(0,0,0,0);
   for(int i = 0; i < numLights; ++i){
        tempColor += ApplyLight(allLights[i]); 
   }
  
   color = LineColor * linearColor * tempColor;


   color.a=transparent;


}



Can somebody tell me how to get rig of this issue? Thanks in Advance.

This is just banding: https://en.wikipedia.org/wiki/Colour_banding

It’s not a fault of your code, it’s because you’re drawing to an 8-bit-per-channel framebuffer (24-bit or 32-bit colour), and is an absolutely standard problem and expected behaviour.

One suggested approach is to do nothing. You’re not blending with a texture yet, and banding is often significantly less noticeable after doing do.

If it really bothers you, you can try drawing to a 64-bit or 128-bit FBO but that will come at some performance tradeoff.

hi mhagain,

Thanks a lot for your info!