I am try to implement a basic spotlight using OpenGL and Fragment Shader. However, I notice that there is a distinct black border artifact at the periphery of the spotlight. I expect to see a hard cut-off between the color inside the spotlight circle and outside the spotlight circle.
The teapot has plain grey color (0.75,0.75,0.75), it is illuminated by :
- a blue point light between the body and the handle
- a red directional light from top right pointing toward the teapot centre
- a green spotlight from the camera toward the body
Here is the fragment shader code (assuming the transformations are done properly in vertex shader and CPU-side):
#version 330 compatibility
#extension GL_ARB_separate_shader_objects : enable
in vec3 oNormal;
in vec3 oPos;
out vec4 Color;
uniform vec3 light0Pos;
uniform vec3 light0Color;
uniform vec3 light1Dir;
uniform vec3 light1Color;
uniform vec3 light2Pos;
uniform vec3 light2Color;
uniform vec3 light2SpotDir;
uniform float light2SpotExp;
uniform float light2SpotCut;
void main()
{
vec3 nNormal = normalize(oNormal);
vec3 surfaceColor = vec3(0.75, 0.75, 0.75);
vec3 tempColor = vec3 (0.0, 0.0, 0.0);
//first light: point light
float w = max(dot(nNormal, normalize(light0Pos - oPos)), 0.0);
tempColor = surfaceColor * vec3(w) * light0Color.xyz;
//second light: directional light
w = max(dot(nNormal, normalize(light1Dir) * vec3(-1.0)), 0.0);
tempColor = tempColor + max(vec3(0.0),surfaceColor * vec3(w) * light1Color.xyz);
//third light: spotlight
vec3 spotDir = normalize(vec3(light2SpotDir));
vec3 light2Dir = normalize(oPos - light2Pos);
w = dot(spotDir, light2Dir);
float c = step(cos(radians(light2SpotCut * 0.5)),w);
w = c * pow(w,light2SpotExp) * max(dot(nNormal, normalize(light2Dir) * vec3(-1.0)), 0.0);
tempColor = tempColor + max(vec3(0.0),surfaceColor * vec3(w) * light2Color.xyz);
Color = vec4(tempColor, 1.0);
}
I suspect there is an interpolation issue. If I check the pixel values, the red pixel which is outside spotlight and near the border has color (87, 0, 0) and the green/yellow pixel which is inside spotlight and near the border has color (83, 66, 0). If it is because of interpolation, the border should have the color like (80, 30, 0). However, the border has color (17, 9, 0) instead...The red channel should not be interpolated.
Thanks!