OpenGL不考虑GL_DIFFUSE位置光的距离

时间:2019-08-04 20:25:25

标签: c++ opengl lighting light opengl-compat

我想在场景中放一个定位灯。我希望远处的物体能减少光线照射,但是opengl只是在乎表面法线和光线之间的角度。我是在做错事还是必须添加其他功能?

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);

运行代码时,即使两个物体具有相同的表面法线,即使它们与光源的距离不同,它们的照明也相同

1 个答案:

答案 0 :(得分:1)

对于距离相关的光,您必须分别设置衰减参数GL_CONSTANT_ATTENUATIONGL_LINEAR_ATTENUATION GL_QUADRATIC_ATTENUATION。参见glLight。默认情况下,灯光是恒定的,与距离无关。

OpenGL 2.0 Specification - 2.14.1 Lighting,第62页中指定了光衰减。
光衰减因子定义为:

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 

恒定衰减的默认值为1,线性和二次衰减的默认值为0。这导致距离无关系数为1。

例如接下来,设置衰减,其中衰减因子为<= 1.0/255.0,距离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);

对于二次衰减,可以通过

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