fukaraadam
fukaraadam

Reputation: 33

OpenGL doesn't consider distance of GL_DIFFUSE positional light

I want to put a positional light in my scene. I expect distant objects to take less light, but opengl just care about angle between surface normal and light. Am I doing something wrong or do I have to add another function?

GLfloat lightIntensity=1.0;
GLfloat main_position[] = {0.0, 0.0, 1.0, 1.0};
GLfloat light_ambient[] = {0.2, 0.2, 0.2, 0.0};
GLfloat light_diffuse[] = {lightIntensity, lightIntensity, lightIntensity, 1.0};
GLfloat light_specular[] = {0.0, 0.0, 0.0, 0.0};

/* Enable a single OpenGL light. */
glLightfv(GL_LIGHT0, GL_POSITION, main_position);
glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);

When I run the code, 2 object with same surface normal have same lighting even though they have different distance from the light source

Upvotes: 2

Views: 368

Answers (1)

Rabbid76
Rabbid76

Reputation: 210948

For a distance dependent light you've to set the attenuation parameters GL_CONSTANT_ATTENUATION, GL_LINEAR_ATTENUATION respectively GL_QUADRATIC_ATTENUATION. See glLight. By default the light is constant independent on the distance.

The light attenuation is specified in OpenGL 2.0 Specification - 2.14.1 Lighting, page 62.
The light attenuation factor is defiend as:

att = 1 / (kc + kl * d + kq * d * d)

d  ... distance from the light source to the fragment
kc ... constant attenuation
kl ... linear attenuation
kq ... quadratic attenuation 

The default value for the constant attenuation is 1, for the linear and quadratic attenuation it is 0. This leads to a distance independent factor of 1.

e.g. In the following a attenuation is set, where the attenuation factor is <= 1.0/255.0 at a distance of max_dist:

float max_dist = ...;
float threshold = 1.0f/255.0f;

float kc = 0.0f;
float kq = 0.0f;
float kl = (1.0f/threshold - kc - kq*max_dist*max_dist) / max_dist;

glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION,  kc);
glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION,    kl);
glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, kq);

For quadratic attenuation the same can be achieved by

float kc = 0.0f;
float kl = 0.0f;
float kq = (1.0f/threshold - kc - kl*max_dist) / (max_dist*max_dist);

Upvotes: 2

Related Questions