c++ - OpenGL不考虑GL_DIFFUSE位置光的距离

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

当我运行代码时,具有相同表面法线的 2 个对象具有相同的光照,即使它们距光源的距离不同

最佳答案

对于距离相关的光,您必须设置衰减参数 GL_CONSTANT_ATTENUATION , GL_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);

关于c++ - OpenGL不考虑GL_DIFFUSE位置光的距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57349994/

相关文章:

c++ - 这五种不同的 cString 声明方式是怎么回事?

c++ - 如何设置正确的 vtkCamera 缩放系数?

c++ - 我什么时候可以发布源 PBO?

c++ - SDL2 : Fast Pixel Manipulation

Python OLA 类型错误 : can only assign array

java - 如何在 JOGL 中正确使用光照?

c++ - 如何在 C++ 中进行 soap 调用

c++ - 在 opengl 矩形上使用着色器会导致它消失

opengl - 延迟渲染和移动点光源

c++ - const 将公共(public)成员引用到私有(private)类成员 - 为什么它有效?