当我在OpenGL中启用照明时,为什么我的颜色会消失?

dan*_*007 26 c++ opengl glut

我正在使用OpenGL API和GLUT在C++中开发一个图形应用程序.

为了添加光照,我在模型视图矩阵中进行了以下更改:

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

// Create light components.
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { 0.0f, 0.0f, 0.0f, 1.0f };

// Assign created components to GL_LIGHT0.
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);
Run Code Online (Sandbox Code Playgroud)

我认为照明在很大程度上起作用,但我的物体的颜色都消失了.我所看到的只是我整体身材的黑/白轮廓.

我想知道为什么会这样?

Chr*_*ica 30

启用光照时,顶点的颜色不是由颜色设置glColorglColorPointer由颜色设置确定的,而是由当前设置的材质颜色与使用光照计算的灯光颜色组合确定的.

因此,为了更改对象的颜色,您需要在渲染之前使用这些glMaterial函数更改材质设置(默认情况下为漫反射灰色材质).对于每种不同的浅色(GL_DIFFUSE,......)基本上存在相应的材料颜色以及一些附加的性质以近似发光材料(GL_EMISSION)和控制材料的粗糙度(GL_SHININESS).阅读有关OpenGL照明功能的一些介绍性材料,以了解它们的工作原理.

如何快速调整代码(从普通颜色到照明(或启用每个顶点材质))可以使用颜色材料.通过调用glEnable(GL_COLOR_MATERIAL)和设置适当的映射,glColorMaterial您可以配置OpenGL以在更改当前顶点颜色时更改特定材质颜色(使用glColor或者glColorPointer).


gen*_*ult 20

试试glEnable(GL_COLOR_MATERIAL).

参见常见的OpenGL陷阱#14:

  1. 小心启用颜色材料

OpenGL的颜色材料功能提供了一种更便宜的方式来更改材料参数.启用颜色材质后,材质颜色会跟踪当前颜色.这意味着glMaterialfv您可以使用该glColor3f例程,而不是使用相对昂贵的 例程.

以下是使用颜色材质功能更改三角形每个顶点的漫反射颜色的示例:

glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glBegin(GL_TRIANGLES);
    glColor3f(0.2, 0.5, 0.8);
    glVertex3f(1.0, 0.0, 0.0);
    glColor3f(0.3, 0.5, 0.6);
    glVertex3f(0.0, 0.0, 0.0);
    glColor3f(0.4, 0.2, 0.2);
    glVertex3f(1.0, 1.0, 0.0);
glEnd();
Run Code Online (Sandbox Code Playgroud)

如果glMaterialfv明确使用,请考虑所需的更昂贵的代码序列:

GLfloat d1[] = { 0.2, 0.5, 0.8, 1.0 };
GLfloat d2[] = { 0.3, 0.5, 0.6, 1.0 };
GLfloat d3[] = { 0.4, 0.2, 0.2, 1.0 };

glBegin(GL_TRIANGLES);
    glMaterialfv(GL_FRONT,GL_DIFFUSE,d1);
    glVertex3f(1.0, 0.0, 0.0);
    glMaterialfv(GL_FRONT,GL_DIFFUSE,d2);
    glVertex3f(0.0, 0.0, 0.0);
    glMaterialfv(GL_FRONT,GL_DIFFUSE,d3);
    glVertex3f(1.0, 1.0, 0.0);
glEnd();
Run Code Online (Sandbox Code Playgroud)

如果要渲染需要频繁更改材质的对象,请尝试使用颜色材质模式.但是,启用色材模式时会遇到常见的陷阱.启用颜色材质后,OpenGL会立即更改颜色材质状态控制的材质颜色.考虑以下代码来初始化新创建的OpenGL渲染上下文:

GLfloat a[] = { 0.1, 0.1, 0.1, 1.0 };
glColor4f(1.0, 1.0, 1.0, 1.0);

glMaterialfv(GL_FRONT, GL_AMBIENT, a);
glEnable(GL_COLOR_MATERIAL); /* WARNING: Ambient and diffuse material latch immediately to the current color. */
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glColor3f(0.3, 0.5, 0.6);
Run Code Online (Sandbox Code Playgroud)

执行上面的代码片段后,前面的环境和漫反射材料的颜色是什么状态?虽然程序员可能已经预期了环境材料状态(0.1, 0.1, 0.1, 1.0)和扩散材料状态(0.3, 0.5, 0.6, 1.0),但事实并非如此.

产生的漫射材料状态是程序员想要的,但是产生的环境材料状态是出乎意料的(1.0, 1.0, 1.0, 1.0).那是怎么发生的?好吧,请记住,颜色材质模式会在启用时立即开始跟踪当前颜色.颜色材料设置的初始值是 GL_FRONT_AND_BACKGL_AMBIENT_AND_DIFFUSE(可能不是您所期望的!).

由于启用颜色材料模式会立即开始跟踪当前颜色,因此环境和漫反射材料状态都会更新为(1.0, 1.0, 1.0, 1.0).请注意,初始化的效果glMaterialfv会丢失.接下来,更新颜色材料状态以仅改变前漫射材料.最后, glColor3f调用将漫反射材质更改为(0.3, 0.5, 0.6, 1.0).环境材料状态最终成为(1.0, 1.0, 1.0, 1.0).

上面的代码片段中的问题是在调用之前启用了颜色材料模式glColorMaterial.颜色材料模式对于有效的简单材料更改非常有效,但为了避免上述缺陷,glColorMaterial在启用之前请务必小心设置GL_COLOR_MATERIAL.