一、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光源位置的更多相关文章

  1. openGL光源概念

    1. 光照模型      环境光——经过多次反射而来的光称为环境光,无法确定其最初的方向,但当特定的光源关闭后,它们将消失. 全局环境光——每个光源都能对场景提供环境光.此外,还有一个环境光,它不来自 ...

  2. OpenGL中glPushMatrix和glPopMatrix的原理

    glPushMatrix.glPopMatrix操作事实上就相当于栈里的入栈和出栈. 很多人不明确的可能是入的是什么,出的又是什么. 比如你当前的坐标系原点在你电脑屏幕的左上方.如今你调用glPush ...

  3. 使用glPushMatrix和glPopMatrix的原因

    转自 百度百科   glPushMatrix 函数将当前矩阵堆栈推送,通过一个,复制当前矩阵. 这就是后 glPushMatrix 的调用堆栈的顶部矩阵是它下面的相同的.   1. 原理讲解 终于明白 ...

  4. OpenGL光照3:光源

    本文是个人学习记录,学习建议看教程 https://learnopengl-cn.github.io/ 非常感谢原作者JoeyDeVries和多为中文翻译者提供的优质教程 的内容为插入注释,可以先跳过 ...

  5. Opengl使用模型视图变换移动光源

    光源绕一个物体旋转,按下鼠标左键时,光源位置旋转. #include <GL/glut.h> static int spin = 0;static GLdouble x_1 = 0.0;s ...

  6. opengl 笔记(2)

    /*- * Opengl Demo Test * * Fredric : 2016-7-10 */ #include <GLUT/GLUT.h> #include <stdlib.h ...

  7. CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果

    CSharpGL(39)GLSL光照示例:鼠标拖动太阳(光源)观察平行光的漫反射和镜面反射效果 开始 一图抵千言.首先来看鼠标拖动太阳(光源)的情形. 然后是鼠标拖拽旋转模型的情形. 然后我们移动摄像 ...

  8. OpenGL阴影,Shadow Volumes(附源程序,使用 VCGlib )

    实验平台:Win7,VS2010 先上结果截图:    本文是我前一篇博客:OpenGL阴影,Shadow Mapping(附源程序)的下篇,描述两个最常用的阴影技术中的第二个,Shadow Volu ...

  9. OpenGL阴影,Shadow Mapping(附源程序)

    实验平台:Win7,VS2010 先上结果截图(文章最后下载程序,解压后直接运行BIN文件夹下的EXE程序): 本文描述图形学的两个最常用的阴影技术之一,Shadow Mapping方法(另一种是Sh ...

随机推荐

  1. bzoj1009

    设f[i,j]为准考证号上第i位匹配到不吉祥数字第j位的方案数,显然j∈[0,m-1]下面我们就要想到怎么把f[i-1]转移到f[i]也就是当前匹配到第k位,那么下一位可能会匹配到哪一位显然我们可以穷 ...

  2. 解决导入lib,关联源码问题

    关联源代码:在libs目录下新建文件,以jar包全名(包括.jar)为文件名称,以.properties结尾 在文件中新建键值对:src=jar包源代码绝对路径:根据提示将单斜线变成双斜线, 然后cl ...

  3. Linux自定义命令

    linux自定义命令,就是给当前命令取个别名.比如:ls 列出当前的文件,rm + 文件名 就能删除该文件,如何自定义命令,可以使用alias比如:alias gobin='cd /opt/tomca ...

  4. robotium源码方法备注---clicker.java

    1.clickOnScreen(float x,float y) 在屏幕上点击一个指定的区域(x,y)横纵坐标 2.clickLongOnScreen(float x,float y, int tim ...

  5. suse linux编译安装GCC报错

    gcc编译安装过程 1.先安装三个库 gmp mprc mpc 这三个库的源码要到官网去下载 1)安装gmp:首先建立源码同级目录 gmp-build,输入命令,第一次编译不通过,发现缺少一个叫m4的 ...

  6. Unity5 Screen-Space Subsurface Scattering屏幕空间次表面散射SSSSS

    用unity5自带的standard shader        ------------by wolf96 

  7. jQuery各种效果举例

    jQuery 所有jQuery详细使用说明请见:http://www.php100.com/manual/jquery/ jQuery的作用是操作浏览器html,从而达到用户的可视化效果,按照功能可分 ...

  8. 用mysqlslap压测mysql

    参考文献:http://my.oschina.net/costaxu/blog/108568 上面网友详细的列举了用mysqlslap对mysql的压力测试结果,我也照葫芦画瓢试了一次,结果如下: 以 ...

  9. 贪心+容器 hdu4268

    Problem Description Alice and Bob's game never ends. Today, they introduce a new game. In this game, ...

  10. kafka集群扩容以及数据迁移

    一 kafka集群扩容比较简单,机器配置一样的前提下只需要把配置文件里的brokerid改一个新的启动起来就可以.比较需要注意的是如果公司内网dns更改的不是很及时的话,需要给原有的旧机器加上新服务器 ...