opengl 光照
来源:互联网 发布:mac无损播放器 编辑:程序博客网 时间:2024/05/22 17:25
文章转自:http://blog.csdn.net/wangdingqiaoit/article/details/51638260
颜色与光照的关系
我们看到的物体的颜色,实际上是光照射物体后反射的光进入眼睛后感受到的颜色,而不是物体实际材料的颜色。太阳的白光包含了所有我们可以感知的颜色,可以将这个白光通过棱镜折射后分离为各种颜色的光。一束白光照射到红颜色的车身上,光经过车身,一部分被吸收,一部分被反射进入人的眼睛,我们感知到的颜色就是这个反射后进入眼睛的光的颜色,如下图所示(来自:Modern OpenGL 06 – Diffuse Point Lighting):
图中,红色的表面吸收了蓝色和绿色成分,将红色反射出来。颜色吸收和反射的过程可以表示为:
计算为:
则上面的过程表示为:
如果将cyan (blue + green) 颜色光束照射到车身,车身会是什么颜色呢?会是黑色的,因为
如果将cyan (blue + green) 颜色照射到magenta (red + blue) 颜色的表面,那么结果会是什么颜色呢?同理,我们可以得到结果颜色为蓝色,如下图所示来自:Modern OpenGL 06 – Diffuse Point Lighting):
在实际场景中,光的强度的各个分量可以在[0,1]之间变化,材料表面的颜色分量也可以在[0,1]之间变化,例如光照射到一个玩具表面的计算过程为:
- 1
- 2
- 3
- 1
- 2
- 3
Phong Reflection Model
要模拟现实的光照是困难的,例如实际光照中,一束光可以经过场景中若干物体反射后,照射到目标物体上,也可以是直接照射到目标物体上。其中经过其他物体反射后再次照射到目标物体上,这是一个递归的过程,将会无比复杂。因此实际模拟光照过程中,总是采用近似模型去接近现实光照。Phong Reflection Model是经典的光照模型,它计算光照包括三个部分:环境光+漫反射光+镜面光,一共三个成分,如下图所示(来自wiki ,作者Brad Smith):
环境光成分
环境光是场景中光源给定或者全局给定的一个光照常量,它一般很小,主要是为了模拟即使场景中没有光照时,也不是全部黑屏的效果。场景中总有一点环境光,不至于使场景全部黑暗,例如远处的月亮,远处的光源。
环境光的实现为:
- 1
- 2
- 3
- 1
- 2
- 3
给定环境光后,场景效果如下图所示:
这里使用了两个着色器绘图。一个着色器用来绘制光源,光源用一个缩小的立方体来模拟,如图中白色立方体所示;另一个着色器用来绘制我们的物体,这里只显示了一个大的立方体。当场景中只有环境光时,立方体只能很暗的显示。
漫反射光成分
漫反射光成分,是光照中的一个主要成分。漫反射光强度与光线入射方向和物体表面的法向量之间的夹角
这里需要的向量包括:
1.光源和顶点位置之间的向量L 需要计算。
2.法向量N 通过顶点属性里指定 经过模型和视变换后需要重新计算。
作为本节的简单示例程序,我们在顶点属性中指定法向量,例如立方体的正面ABCD这个面的顶点属性如下所示:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
和顶点位置属性一样,我们需要将法向量数据发送到GPU,并且使用glVertexAttribPointer告诉OpenGL数据的解析方式。这些内容在前面已经介绍了,这里不再赘述。
将顶点属性传递到着色器后,需要在着色器中开始我们的光照计算。有两种方法执行向量L和N的计算。一种方式是在世界坐标系中计算,另一种是在相机坐标系中计算,两种方法都可以实现。
这里以在世界坐标系中计算L和N为例进行说明,在相机坐标系中计算也有类似操作。在世界坐标系中,计算L时,光源lightPos是在世界坐标系中指定的位置,直接使用即可。顶点位置需要变换到世界坐标系中,利用Model矩阵即可,使用式子:
在计算N时需要注意,我们不能直接利用
这个式子的具体推导过程,可以参考The Normal Matrix。
综上所述,顶点着色器中计算顶点位置和法向量代码为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
在片元着色器中,计算漫反射光成分的代码为:
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
这里使用max(dot(lightDir, normal), 0.0)主要是为了防止当光线和法向量夹角大于90后,取值为负的情况,因此使用max保证漫反射光照系数在[0.0,1.0]范围内。
添加了漫反射光成分后的效果如下图所示:
镜面反射光成分
镜面光成分模拟的是物体表面光滑时反射的高亮的光,镜面光反映的通常是光的颜色,而不是物体的颜色。计算镜面光成分时,要考虑光源和顶点位置之间向量L、法向量N、反射方向R、观察者和顶点位置之间的向量V之间的关系,如下图所示(来自:Lighting and Material):
当R和V的夹角
其中
计算镜面光成分过程为:
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
这里需要注意的是,利用reflect函数计算光的出射方向时,要求入射方向指向物体表面位置,因此这里翻转了lightDir,计算为:
- 1
- 1
将上述三种光成分叠加后,成为最终物体的颜色,片元着色器中实现为:
- 1
- 2
- 1
- 2
绘制效果如下图所示:
per-vertex 和per-fragment实现光照的对比
上面我们实现的光照计算是在片元着色器中进行的,这种是基于片元计算的,称之为Phong shading。在过去OpenGL编程中实现的是在顶点着色器中进行光照计算,这是基元顶点的计算的,称之为Gouraud Shading。Gouraud Shading和Phong shading,两者的效果对比如下图所示(来自learnopengl.com Basic Lighting):
基元顶点计算光照的优势在于顶点数目比片元数目少,因此计算速度快,但是基于顶点计算的光照没有基元片元的真实,主要是基元顶点计算时,只计算了顶点的光照,而其余片元的光照由插值计算得到,这种插值后的光照显得不是很真实,需要使用更多的顶点来加以完善。例如下面的图中,分别显示了使用少量和大量顶点的基于顶点的光照计算效果:
使用基于片元的光照计算时能够获取更为平滑的光照效果。实现基元顶点的光照计算过程,即将上述在片元着色器中的光照计算过程迁移到顶点着色器中执行。
最后的说明
在计算光照的过程中,注意使用的向量一定要单位化,因为
实现的Phong reflection model还不够完善,一方面从光源角度看,属于点光源,但是缺少随着距离的衰减;另一方面从物体的材质角度看,没有反映出物体不同部分对光感受的强度不同这一特点,需要使用材质属性加以改进。
- OpenGL光照
- opengl光照
- OpenGL光照
- OpenGL光照
- opengl 光照
- OpenGL--光照
- OpenGL光照
- OpenGL光照
- opengl光照
- OpenGL光照
- OpenGL光照
- opengl 光照
- openGL-光照
- OpenGL中的光照[光照计算]
- 关于OpenGL光照问题
- OpenGL中的光照
- OpenGL 光照常识
- OpenGL 光照常识
- Mysql修改登录密码
- js中的onload
- oracle通过dblink连接mysql配置详解(全Windows下)
- Linux 安装
- mysql:安装
- opengl 光照
- 传输层流协议:RTP/RTCP、SCTP、DCCP、RTSP
- 【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示
- 复习
- 414. Third Maximum Number
- MySql存储(逻辑判断/条件控制/循环控制)
- android adb与fastboot 常用命令
- 最大连续子序列和
- 协议森林03 IP接力赛 (IP, ARP, RIP和BGP协议)