光照模型

在OpenGL光照模型中,除非一个物体自己会发光,否则它将受到3种不同类型的光的照射:环境光(ambient)、散射光(diffuse)和镜面光(specular)。

  • 全局环境光 在我们没有用到光照之前,我们也能够看到场景中绘制的物体,原因是每个场景都有这个全局环境光,它不来自任何特定的光源。
  • 环境光(ambient) 环境光并不来自任何特定的方向。它来自某个光源,但光线却是在房间或场景中四处反射,没有方向可言。由环境光所照射的物体在所有方向的表面都是均匀照亮的。
  • 散射光(diffuse) 散射光具有方向性,来自于一个特定的方向,它根据入射光线的角度在表面上均匀地反射开来。
  • 镜面光(specular) 镜面光具有很强的方向性,但它的反射角度很锐利,只沿一个特定的方向反射。

光源与材料

光源

OpenGL可以同时为我们提供8个有效的光源。也就是说,我们最多可以同时启用8个光源。它们分别是GL_LIGHT0,GL_LIGHT1,GL_LIGHT2 …… 其中,GL_LIGHT0是最特殊的一个光源,我们可以为GL_LIGHT0指定环境光成分。在默认情况下,GL_LIGHT0光源的颜色为白光,其他7个光源在默认情况下是没有颜色的,也

即为黑色。

光源种类

  • 环境光 环境光是一种无处不在的光。环境光源放出的光线被认为来自任何方向。因此,当你仅为场景指定环境光时,所有的物体无论法向量如何,都将表现为同样的明暗程度。
  • 点光源 由这种光源放出的光线来自同一点,且方向辐射自四面八方。
  • 平行光 平行光又称镜面光,这种光线是互相平行的。从手电筒、太阳等物体射出的光线都属于平行光。
  • 聚光灯 这种光源的光线从一个锥体中射出,在被照射的物体上产生聚光的效果。使用这种光源需要指定光的射出方向以及锥体的顶角α。

设置光源

1.设置环境光成分

对于GL_LIGHT0,我们可以为其指定环境光成分。调用

glLightfv(GL_LIGHT0,GL_AMBIENT,@AmbientLight);

在上述函数调用中,第一个参数表示我们要对GL_LIGHT0进行设置;
第二个参数表示我们要设置的是环境光成分;
第三个参数则是一个数组,它有4个值,分别表示光源中含有红、绿、蓝三种光线的成分,一般情况下都为1;
第四个参数为透明度值,一般也为1。
完整的代码是这样的:

void SetLight
{int AmbientLight[4]={1,1,1,1};glLightfv(GL_LIGHT0,GL_AMBIENT,@AmbientLight);glEnable(GL_LIGHT0);       //开启GL_LIGHT0光源glEnable(GL_LIGHTING);     //开启光照系统
}

2.设置漫射光成分

通过对漫射光成分的设置,我们可以产生一个点光源。方法和设置环境光成分相似,只需调用

 glLightfv(GL_LIGHT0,GL_DIFFUSE,@DiffuseLight);

其中DiffuseLight是漫射光的颜色成分。可以根据不同需要指定不同的颜色,一般情况下也为(1,1,1,1)。

3.设置镜面光成分

通过对镜面光成分的设置,我们可以产生一个平行光源。方法和设置漫射光成分相似,只需调用

glLightfv(GL_LIGHT0,GL_SPECULAR,@SpecularLight);

其中SpecularLight是镜面反射光的颜色成分。可以根据不同需要指定不同的颜色。

4.设置光源的位置

对于点光源和平行光源,我们常常需要指定光源的位置来产生需要的效果。方法仍然是调用glLightfv函数,仅仅是换换参数而已:

glLightfv(GL_LIGHT0,GL_POSITION,@LightPosition);

其中,LightPosition也是一个四维数组,四维数组的前3项依次为光源位置的X,Y,Z分量。
第四个值很特殊,一般为1或0。当LightPosition[4]=0的时候,表示光源位于距离场景无限远的地方,相当于平行光;而当LightPosition[4]=1时,光源的位置就是前三项所

指定的位置,也就是成为了点光源。

材料

材料是针对场景中的物体而言的,但并不是指现实生活中构成物体的那种有质感材料,这里的材料只与物体的颜色有关(你可能会想到怎样表现类似金属、玻璃等物质质感,

除了要使用光照系统并为它们指定合适的材质外,还要使用纹理贴图来表现)。OpenGL用材料对光的红、绿、蓝三原色的反射率来近似定义材料的颜色。当一束光照到物体上

时,光本身有颜色(可以自己指定。通常情况下的白光是RGB三色光的混合),光照到物体上时,物体的材料会根据自身对光中的各种成分的反射参数决定反射哪种光,也就是物

体所呈现出的颜色啦。所以并不是什么颜色的光照过来,物体就会呈现出什么颜色的光。

设置材料

材质的设置与光源的设置类似。其函数为:

void glMaterial{if}[v](GLenum face,GLenum pname,TYPE param);

face可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK,它表明当前材质应该应用到物体的哪一个面上;
pname说明一个特定的材质;
param是材质的具体数值,若函数为向量形式,则param是一组值的指针,反之为参数值本身。非向量形式仅用于设置GL_SHINESS。pname参数值具体内容见下表。另外,

参数GL_AMBIENT_AND_DIFFUSE表示可以用相同的RGB值设置环境光颜色和漫反射光颜色。

完整代码如下:

void SetMaterialAndLight
{GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat mat_shininess[] = { 50.0 };GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };  //最后一个参数为0表示该光源是directional的//GLfloat light_position[] = { 1.0, 1.0, 1.0, 1.0 };  //最后一个参数非0表示该光源是positional的GLfloat light_ambient[] = { 0.0, 1.0, 0.0, 1.0 };GLfloat light_diffuse[] = { 0.0, 1.0, 0.0, 1.0 };GLfloat light_specular[] = { 0.0, 1.0, 0.0, 1.0 };glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);glLightfv(GL_LIGHT0, GL_POSITION, light_position);glEnable(GL_LIGHT0);       //开启GL_LIGHT0光源glEnable(GL_LIGHTING);     //开启光照系统
}

颜色追踪

在没有学习光照之前,我们是通过glColor()函数来指定物体颜色的,前面已经说过,这时候我们能看到我们所设置的物体颜色是因为有全局环境光的原因。当开启光照功能后,

如果用上述的设置材料属性的方法进行设置,则原来设置的颜色与被光照到后物体呈现的颜色毫无关系,即原来的 glColor*()命令失去原有的作用。
但还有一种方法设置材料属性的方法,称为颜色追踪,即用颜色指定代替材料属性指定。使用颜色追踪,可以告诉OpenGL仅仅通过调用glColor来设置材料属性。为了启用

颜色追踪,需要以GL_COLOR_MATERIAL为参数调用glEnable。接着,glColorMaterial函数根据glColor所设置的值来指定材料参数。

glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);

如果调用了 glEnable(GL_COLOR_MATERIAL),那么就会使光照模型中的几种光根据glColor*()中的指定确定颜色;

void glColorMaterial(GLenum face, GLenum mode);

– face的取值GL_FRONT, GL_BACK与GL_FRONT_AND_BACK(默认值)
– mode的取值为GL_EMISSION, GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR与 GL_AMBIENT_AND_DIFFUSE(默认值)
例如:

glEnable(GL_COLOR_MATERIAL);
glColorMaterial(GL_FRONT, GL_DIFFUSE); /* now glColor* changes diffuse reflection */
glColor3f(0.2, 0.5, 0.8);/* draw some objects here */ glColorMaterial(GL_FRONT, GL_SPECULAR); /* now glColor* changes specular reflection */
glColor3f(0.9, 0.0, 0.2);/* draw other objects here */
glDisable(GL_COLOR_MATERIAL);

另外,不需要使用glColorMaterial()时,确保禁用。

材质RGB值和光源RGB值的关系

材质的颜色与光源的颜色有些不同。对于光源,R、G、B值等于R、G、B对其最大强度的百分比。若光源颜色的R、G、B值都是1.0,则是最强的白光;若值变为0.5,颜色仍为

白色,但强度为原来的一半,于是表现为灰色;若R=G=1.0,B=0.0,则光源为黄色。对于材质,R、G、B值为材质对光的R、G、B成分的反射率。比如,

一种材质的R=1.0,G=0.5,B=0.0,则材质反射全部的红色成分,一半的绿色成分,不反射蓝色成分。也就是说,若OpenGL的光源颜色为(LR,LG,LB),

材质颜色为(MR,MG,MB),那么,在忽略所有其他反射效果的情况下,最终到达眼睛的光的颜色为(LRMR,LGMG,LB*MB)。同样,如果有两束光,相应的值分别为(R1,G1,B1)和

(R2,G2,B2),则OpenGL将各个颜色成分相加,得到(R1+R2,G1+G2,B1+B2),若任一成分的和值大于1(超出了设备所能显示的亮度)则约简到1.0。

OpenGL 光照模效果的原理

OpenGL的光照模型是用来模拟现实生活中的光照的。它根据顶点的法线向量光源的位置决定顶点的明暗程度,根据顶点的材质光源中三原色的成分来决定物体将

表现出怎样的颜色

使用OpenGL的光照模型的步骤:

  • 设置光源的种类、位置和方向(对于平行光源)
  • 为每个图元的每个顶点指定它的法线向量
  • 为各个图元指定它的材料

步骤1和步骤3上面已经说过了,下面解释一下步骤2。
众所周知,光线是根据物体表面法向来确定其反射方向的,所以想要对开启光照效果就要对物体表面的每个图元指定法向。如果场景中的物体是多边形网格模型,则需要自己

计算每个网格的法向量然后再调用glNormal*()为每个网格指定法线向量。当然,如果你用的是类似glutSolidTorus()或者glutSolidSphere()这种GLUT工具包中的函数则不用

自己指定图元的法向量。

作者:Beatrice7
链接:http://www.jianshu.com/p/1da6ae890ef3
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

OpenGL光源光照基础相关推荐

  1. OpenGL学习: 光照系列3-光源类型和使用多个光源

    写在前面  上一节光照中使用材质和lighting maps介绍了使用材质属性和lighting maps使物体的光照效果能反映物体的材料特性,看起来更逼真.在前面的章节中使用的实际上都是一个点光源, ...

  2. UnityShader9.1:光照基础实例

    前置:UnityShader9:光照基础回顾 一.漫反射光照 直接上代码: 注意其中 Tags 需要设置光照模式为 ForwardBase,它定义了该 Pass 在光照流水线中的角色,在不同的光照模式 ...

  3. UnityShader9:光照基础回顾

    一.需要提前了解的 基于经验的基础光照,相比于后面物理光照的学习,简单不少: 光照基础:https://blog.csdn.net/Jaihk662/article/details/106624451 ...

  4. OpenGL光源位置

    一.OpenGL光源简介 OpenGL提供了多种形式的光源,如点光源.平行光源和聚光灯光源等.所有光源都使用 glLight*接口来设置光源属性,其中包括 glLight{if} 和 glLight{ ...

  5. 【OpenGL】光照太阳系

    一.要求 二.思路 0.效果图 1.实现基本的太阳系 采用局部变换的思路完成,实现太阳.地球.月亮及轨道的绘制 2.宇宙中加入一盏泛光(方向光) 加入思路: 1)设置好物体的法向 在这里可以不进行设置 ...

  6. OpenGL着色器基础

    前言: 本文翻译自LearnOpengl经典教程,OpenGL着色器基础介绍的比较通俗易懂,特总结分享一下! 为什么要使用着色器? 我们知道,OpenGL一般使用经典的固定渲染管线来渲染对象,但是随着 ...

  7. OpenGL Lightmap光照贴图的实例

    OpenGL Lightmap光照贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #include ...

  8. OpenGL 高级光照Advanced Lighting

    OpenGL高级光照Advanced Lighting 高级光照Advanced Lighting简介 Blinn-Phong 高级光照Advanced Lighting简介 在光照小节中,我们简单地 ...

  9. QT+OpenGL高级光照 Blinn-Phong和Gamma校正

    QT+OpenGL高级光照1 本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主 Blinn-Phong 冯氏光照:视线与反射方向 ...

  10. OpenGL基础18:光照基础

    真实的光照非常的复杂,所以有关光照的算法和论文也有不少,想要模拟出更真实的光照往往需要很强的实力,很牛的算法以及很高的数学/物理水平,与此相关的技术到现在为止也只是在发展中(包括目前比较火的" ...

最新文章

  1. 心累了,就笑一笑,学会爱自己
  2. c++ iou学习笔记
  3. 移动服务机器人模块选型
  4. 建立自己的git账户并保存资料的重要性
  5. WebKit Event
  6. mb_internal_encoding php,PHP字符串mbstring处理中文字符串的具体方法解析
  7. bzoj1974 [Sdoi2010]代码拍卖会 循环+背包
  8. 如果我建一个外卖平台,不收取商家佣金和骑手提点,会不会成功?
  9. 简单模拟多线程Socket通信(java)
  10. 阶段1 语言基础+高级_1-3-Java语言高级_07-网络编程_第2节 TCP协议_4_TCP通信的服务器端代码实现...
  11. 镁光固态硬盘用什么软件测试寿命,最简单的方法:如何查看SSD可以使用多长时间?固态硬盘寿命测试方法[详细]...
  12. matlab2008 软件下载及安装教程
  13. github访问加速
  14. TensorFlow版BERT源码详解之self-attention
  15. Python格式化输出%.2f%%
  16. **懒得给孩子讲故事怎么办**
  17. 2018 ICPC焦作站 F题 Honeycomb【bfs】
  18. dex2jiar在压缩classes.dex的时候出现的问题
  19. vba工作表重命名_如何在Excel中重命名工作表选项卡
  20. Java集合系列(一):List、Map、Set的基本实现原理总结

热门文章

  1. 淘宝客小程序制作(3)-API编写及部署
  2. 如何为摇滚音乐选择吉他音箱,创作原创音乐
  3. [NTUSTISC pwn LAB 2]栈溢出:gdb动态调试bof2
  4. xxl-job整合到微服务
  5. win10下装mysql-5.7.18-winx64
  6. 二维正态分布参数rho的作用
  7. 不良资产证券化信披 担任怎样的角色
  8. 5月6阴阳师服务器维护,《阴阳师》手游5月6日维护更新公告
  9. springboot整合xxl-job分布式定时任务【图文完整版】
  10. IdentityServer4揭秘---Consent(同意页面)