OpenGL启用光照后glColor设置的物体颜色变白原因及解决方法
问题原因
OpenGL固定功能管线的顶点颜色计算逻辑,根据光照开关状态走两套独立流程:
- 未启用
GL_LIGHTING时,光栅化阶段直接读取glColor3f设置的当前顶点颜色作为输出,因此设置的红色可以正常显示。 - 启用
GL_LIGHTING后,顶点最终颜色由光源参数、当前绑定的材质属性、顶点法线方向共同计算得出。默认配置下glColor3f设置的颜色不会参与光照计算流程,光照计算环节只会读取通过glMaterial*系列接口设置的材质参数。
代码未显式设置任何材质参数时,OpenGL默认的正面材质环境+漫反射属性为接近(0.8,0.8,0.8)的浅灰色,配合GL_LIGHT0默认的(1,1,1)白色光源,最终渲染结果就会呈现白色/浅灰色,完全忽略glColor3f设置的红色。
可行解决方法
可根据渲染需求选择以下两种方案:
方案1:启用颜色材质关联(最简便,适配原有代码逻辑)
开启GL_COLOR_MATERIAL状态,让glColor设置的颜色自动同步到材质属性,无需修改原有glColor3f的调用逻辑。
修正后的代码示例:
glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); // 开启颜色材质追踪,默认将glColor值同步到材质的环境+漫反射通道 glEnable(GL_COLOR_MATERIAL); glLoadIdentity(); glTranslatef(0.0f + deltaA - deltaD, 0.0f + deltaQ - deltaE, 0.0f + deltaW - deltaS); glRotatef(_rotate_x, 1, 0, 0); glRotatef(_rotate_y, 0, 1, 0); glColor3f(1.0f, 0.0f, 0.0f); glutSolidSphere(20, 15, 15); glDisable(GL_COLOR_MATERIAL); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0);
如果需要调整颜色同步的材质通道,可以调用glColorMaterial(GLenum face, GLenum mode)指定,默认参数已经覆盖绝大多数常规渲染需求。
方案2:显式设置材质属性(适合精细控制材质效果)
如果需要控制高光、自发光等更丰富的材质效果,可以直接调用glMaterial*接口设置材质参数,不再依赖glColor传值。
示例代码:
glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLoadIdentity(); glTranslatef(0.0f + deltaA - deltaD, 0.0f + deltaQ - deltaE, 0.0f + deltaW - deltaS); glRotatef(_rotate_x, 1, 0, 0); glRotatef(_rotate_y, 0, 1, 0); // 显式设置红色材质 GLfloat mat_red[] = {1.0f, 0.0f, 0.0f, 1.0f}; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_red); // 如需设置白色高光、高光系数可补充以下代码 // GLfloat mat_spec[] = {1.0f,1.0f,1.0f,1.0f}; // glMaterialfv(GL_FRONT, GL_SPECULAR, mat_spec); // glMaterialf(GL_FRONT, GL_SHININESS, 30.0f); glutSolidSphere(20, 15, 15); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0);
补充说明
GLUT内置的glutSolidSphere已经内置了正确的法线数据,不需要额外手动计算传入法线,只要正确设置材质/开启颜色材质关联即可得到正确的光照着色效果。
内容的提问来源于stack exchange,提问作者Keastmin
相关产品推荐
相关产品推荐

