OpenGL光源位置
2017-08-16 15:28
148 查看
一、OpenGL光源简介
OpenGL提供了多种形式的光源,如点光源、
平行光源和
聚光灯光源等。所有光源都使用
glLight*接口来设置光源属性,其中包括 glLight{if} 和 glLight{if}v 两类。
1、示例光源
GLfloat ambient[] = {0.3f, 0.3f, 0.3f, 1.0f}; // 环境强度 GLfloat diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 散射强度 GLfloat specular[] = {1.0f, 1.0f, 1.0f, 1.0f}; // 镜面强度 // 点光源, GL_POSITION属性的最后一个参数为1 GLfloat position[] = {-3.0f, -3.4f, -8.8f, 1.0f}; glLightfv(GL_LIGHT0, GL_POSITION, position); glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT0, GL_SPECULAR, specular); // 平行光源, GL_POSITION属性的最后一个参数为0 GLfloat direction[] = {-3.0f, -3.4f, -8.8f, 0.0f}; glLightfv(GL_LIGHT1, GL_POSITION, direction); glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT1, GL_SPECULAR, specular); // 聚光灯光源, 需要指定位置、方向、光锥半角 GLfloat spot_direction[] = {-3.0f, -3.4f, -8.8f}; glLightfv(GL_LIGHT2, GL_POSITION, position); glLightfv(GL_LIGHT2, GL_SPOT_DIRECTION, spot_direction); glLightfv(GL_LIGHT2, GL_SPOT_CUTOFF, 45.0); glLightfv(GL_LIGHT2, GL_AMBIENT, ambient); glLightfv(GL_LIGHT2, GL_DIFFUSE, diffuse); glLightfv(GL_LIGHT2, GL_SPECULAR, specular);
2、注意事项
最大光源数:不同的硬件支持的光源数量不一样,但至少会支持8个光源。表示光源的常量有GL_LIGHT0、GL_LIGHT1、GL_LIGHT2、...、GL_LIGHT7、...等。在片段着色中可通过
gl_LightSource[0]、gl_LightSource[1]、gl_LightSource[2]、...、gl_LightSource[7]、...等内建变量访问各个光源的参数;
启用和关闭光源 :可通过
glEnable(GL_LIGHTING)启用光照机制,然后使用
glEnable(GL_LIGHTx)与
glDisable(GL_LIGHTx)打开或关闭相应光源(其中x代表光源序号);
模型顶点必须指定法向:OpenGL光照机制是通过计算物体表面法向与入射光线的夹角来确定表面的亮度。故若传入的模型没有指定法向,则最终结果会变得一片漆黑;若法向有问题,最终结果也会莫名其妙。
二、控制光源的位置和方向
控制光源的矩阵变换和控制图元的矩阵变换相同,故最终光源表现出来的性质(如点光源位置是固定在世界坐标系某点还是跟随镜头移动,平行光源的方向在世界坐标系下是不变的还是跟随相机移动等)与提交光源位置或朝向(glLight*())和视点变换(gluLookAt())的先后顺序是息息相关的。据此我们可以定义出各式各样的常见光源,如太阳光、白炽灯、汽车前照灯等。1、定义在世界坐标系下的光源
如果在视点变换后提交光源位置或朝向,那么光源就可以看作一个普通的几何对象,提交的坐标是在世界坐标系中度量的,对普通几何对象的各种变换同样适用于光源。可通俗的理解为视图变换矩阵作用于光源的位置或朝向参数上,此过程就如同世界坐标系下的普通物体转换至观察坐标系下。如果程序里没有视点变换,说明世界坐标系和摄像机坐标系重合,光源也可以看作一个普通的几何对象。表现出这种性质的常见光源有太阳光,家里的白炽灯等。示例代码如下:
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); GLfloat sun_light_position[] = {-139.5f, -153.4f, -68.8f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); // 光源的其他参数可在程序初始化时设置 glPushMatrix(); glTranslated(-2.5, 6.9, -184.8); glRotated(87.4, 0, 0, 1); drawOBJ(); glPopMatrix(); ... }
注意:光源位置或朝向的指定不能处于某个模型的模型变换代码之间(如上例中的glPushMatrix()与glPopMatrix()之间),否则光源参数会受到影响。所以最好将光源位置或朝向设置代码放在紧跟gluLookAt之后。
2、定义在相机坐标系下的光源
如果在视点变换前提交光源位置,视点和光源将捆绑在一起,即二者相对位置不变,一起运动。此时,可以理解为提交的光源位置是在相机坐标系中度量的(位置参数的默认值是(0.0, 0.0, 1.0, 0.0), 就是在摄像机坐标系中度量的)。亦可通俗的理解为视图变换矩阵未作用于光源的位置或朝向参数上。光源的位置朝向参数在观察坐标系的值会保持不变。表现出这种性质的常见光源有汽车前照灯(以驾驶员的视角观察视角)或矿工头上的矿灯。示例代码如下:
void myDisplay() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GLfloat sun_light_position[] = {-139.5f, -153.4f, -68.8f, 0.0f}; glLightfv(GL_LIGHT0, GL_POSITION, sun_light_position); // 光源的其他参数可在程序初始化时设置 gluLookAt(0, 0, 0, 0, 0, -1, 0, 1, 0); glPushMatrix(); glTranslated(-2.5, 6.9, -184.8); glRotated(87.4, 0, 0, 1); drawOBJ(); glPopMatrix(); ... }
相关文章推荐
- OpenGL光源位置
- OpenGL-光源位置的控制
- Win32+OpenGL计算机图形学光照阴影算法 可控制光源、光照物等位置的移动以及漫游等
- opengl设置了光源之后,画图的颜色设置为什么不生效了?怎么改?
- OPENGL光源(shader部分)整体实现思想
- opengl平行光光源,点光源,聚光灯光源同台出现
- QT_OpenGL设置窗口出事位置和大小
- openGL之光照2(材料、颜色追踪、光源)---openGL学习笔记(十)
- 纹理滤波方式、光源:Jeff Molofee(NeHe) 的 OPENGL 教程-第七课
- OpenGL进阶(十九) - 多光源
- opengl绘制在屏幕坐标中固定位置的坐标轴模型
- opengl对三种光源(方向光,点光源,聚光灯)进行特写并分屏渲染
- OpenGL(十二) 光源类型 平行光 、 点光源 、 聚光灯 的实现
- OpenGL光源的移动解释
- OpenGL学习脚印:光源类型和使用多个光源(Light source and multiple lights)
- OpenGL深入探索——点光源中的法向量计算
- NeHe的OpenGL教程7(Bang翻译Delphi版)-如何使用光源
- OpenGL学习之材质RGB值和光源RGB值关系
- Opengl_20 _复习变换矩阵+复习光源+两个模型使用不同的shader
- openGL 在光源处画一个球,移动光源