I’ve been working OpenGL’s Superbible (5th Edition) point light examples.
I found them missing the constant, linear and quadratic attenuation values integrated into the old lighting model, so I went and wrote a point light shader with attenuation values based on Point Light Attenuation this ogre guide.
The results have been completely bizarre. What can be done to get a sensible light attenuation on the new glsl? Is there a glsl table for attenuation constants?
Sample vertex and fragment programs:
Vertex program:
//point light per pixel vertex program
#version 130
// Incoming per vertex... position and normal
in vec4 vVertex;
in vec3 vNormal;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform mat3 normalMatrix;
uniform vec3 vLightPosition;
// Color to fragment program
smooth out vec3 vVaryingNormal;
smooth out vec3 vVaryingLightDir;
out float dist;
out float constantAttenuation;
out float linearAttenuation;
out float quadraticAttenuation;
void main(void)
{
// Get surface normal in eye coordinates
vVaryingNormal = normalMatrix * vNormal;
// Get vertex position in eye coordinates
vec4 vPosition4 = mvMatrix * vVertex;
vec3 vPosition3 = vPosition4.xyz / vPosition4.w;
//get distance to light source
dist=length(vLightPosition-vPosition3);
//write proper attenuation values
if (dist<7.0){
constantAttenuation=1.0;
linearAttenuation=0.7;
quadraticAttenuation=1.8;
}
else if (dist<13.0){
constantAttenuation=1.0;
linearAttenuation=0.35;
quadraticAttenuation=0.44;
}
else if (dist<20.0){
constantAttenuation=1.0;
linearAttenuation=0.22;
quadraticAttenuation=0.20;
}
if (dist<32.0){
constantAttenuation=1.0;
linearAttenuation=0.14;
quadraticAttenuation=0.07;
}
if (dist<50.0){
constantAttenuation=1.0;
linearAttenuation=0.09;
quadraticAttenuation=0.32;
}
if (dist<65.0){
constantAttenuation=1.0;
linearAttenuation=0.07;
quadraticAttenuation=0.017;
}
if (dist<100.0){
constantAttenuation=1.0;
linearAttenuation=0.045;
quadraticAttenuation=0.0075;
}
// Get vector to light source
vVaryingLightDir = normalize(vLightPosition - vPosition3);
// Don't forget to transform the geometry!
gl_Position = mvpMatrix * vVertex;
}
Fragment program:
//point light per pixel fragment program
#version 130
out vec4 vFragColor;
uniform vec4 ambientColor;
uniform vec4 diffuseColor;
uniform vec4 specularColor;
smooth in vec3 vVaryingNormal;
smooth in vec3 vVaryingLightDir;
in float dist;
in float constantAttenuation;
in float linearAttenuation;
in float quadraticAttenuation;
void main(void){
float att;
att = 1.0 / constantAttenuation + linearAttenuation*dist +quadraticAttenuation*dist*dist;
// Dot product gives us diffuse intensity
float diff = max(0.0, dot(normalize(vVaryingNormal), normalize(vVaryingLightDir)));
// Multiply intensity by diffuse color, force alpha to 1.0
vFragColor = att*(diff * diffuseColor +ambientColor); // attenuation affects the diffuse component
// Specular Light
vec3 vReflection = normalize(reflect(-normalize(vVaryingLightDir), normalize(vVaryingNormal)));
float spec = max(0.0, dot(normalize(vVaryingNormal), vReflection));
if(diff != 0) {
float fSpec = pow(spec, 128.0);
vFragColor.rgb += (att*vec3 (fSpec, fSpec, fSpec)); // attenuation affects the specular component
}
}