PDA

View Full Version : Lighting ring artifact!



HanWu
10-14-2017, 08:33 PM
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.

mhagain
10-15-2017, 04:07 AM
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.

HanWu
10-15-2017, 07:12 PM
hi mhagain,

Thanks a lot for your info!