各种光照的算法原理 菲涅尔法则
Per Pixel Lighting Techniques
飘飘白云译 2008-03-22
原文链接:http://www.nitrogen.za.org/viewtutorial.asp?id=5
这个教程用到了向量数学知识,如果你对向量数学还不是很了解,请先阅读向量教程:read the tutorial。
光照与物体表面的相互作用可以通过将一些数学公式应用于基于per pixel(区别于基于顶点)的着色,从而模拟出真实生活中的各种材质效果。比如浮雕效果,波浪效果,油漆效果等。
在这个教程中,我们有如下假定:
第一,我们讨论的是基于像素着色(per-pixel basis),每个pixel有它自己的位置向量,法线向量以及表面颜色(Surface color,在这里可以是来自纹理的颜色,也可以是RGB颜色(flat color));
第二,表面颜色(Surface color)通常是由R,G,B三部分组成,在这个教程中,我们把它当作一个向量看待;
第三,输入表面颜色(光照处理前的表面颜色,这里的“输入”可以理解为函数的输入参数的“输入”)只是普通的颜色(单纯的纹理颜色或者RGB颜色),而输出表面颜色(光照处理后的表面颜色)是光照作用于表面的合成颜色,如可以是有阴影,高光等效果的颜色。
第四,这个教程中假设每个场景中只有一个灯光。对于多灯光的场合,对每一个灯光循环进行这些运算(环境光除外)。
好了,让我们开始讲解各种光照的算法原理
Ambient Lighting 环境光
在真实生活里,有光线的房子里的物体不会是全黑的,总有一些光量子照亮物体表面,即使这个表面是背对光源的,这就是环境光的原因。我们不考虑环境光的照射方向,我们总认为场景中的物体,不论它在什么位置,总会受到一定数量的环境光照射(全局照明)。环境光照算法如下:
Inputs:
Col – 物体原表面颜色
AmbAmount – 场景中环境光的强弱程度 (介于0 到 1之间)
Outputs:
SurfaceColor – 环境光照作用之后的表面颜色
SurfaceColor = Col*AmbAmount;
环境光照效果图:
Lambert Shading (郎伯特着色,郎伯特:物理上的亮度单位,在这里就是漫射光作用)
现在我们真正开始考虑一束光照射在物体表面上的作用过程,我们使用最常见的光照算法-------漫反射光照着色或者说郎伯特余弦定律或郎伯特着色(三个都一回事),这个算法是将入射光与表面法线向量的点积当作漫反射光照强度因子,下面我们看看环境光照与漫射光照共同作用的算法:
Inputs:
LCol – 照射在表面上的漫射光
Pos – 表面上被照射的位置
LPos – 漫射光源的位置
N -表面上被照射的位置处的法向量
Col –物体原表面颜色
AmbAmount -场景中环境光的强弱程度 (0 to 1)
Outputs:
SurfaceColor -环境光照与漫射光照共同作用之后的表面颜色
VectorToLight = Normalise(LPos - Pos);
DiffuseFactor = Dot(VectorToLight, Normal); //DiffuseFactor ranges from 0 to 1
//光线与表面法线夹角大于90度,想像下光线在表面背面射过来,正表面肯定没有光照
if(DiffuseFactor < 0)
then DiffuseFactor = 0;
//环境光照与漫射光照共同作用
SurfaceColor = Col*AmbAmount + Col*DiffuseFactor*LCol;
环境光与漫射光共同作用效果
Specular Highlights镜面高光
现在我们考虑物体表面有光泽的效果,这种效果是将Phong反射模型,结合前面两个光照作用而成。这中光照效果计算需要知道观察者在场景中的位置,而先前的环境光照与漫射光照效果计算都与观察者所在位置无关的。
这种光照计算是这样的,首先我们计算入射光在表面处的反射光线,然后再将反射光线与视线(观察者的眼睛与表面观察点的连线)之间的点积值当作反射到观察者眼中的光照强度因子,因为表面上高亮的部分是反射光线反射到观察者眼睛或照相机中较多的地方,这些地方的反射光线与视线之间的夹角非常小,点积值就越大。
Inputs:
ViewPos – 观察者的位置
SpecAmount – 镜面光强弱. (from 0 to about 200)
SpecCol – 镜面光颜色(通常为白色).
LCol – 照射在表面上的漫射光
Pos – 表面上被照射的位置
LPos – 漫射光源的位置
N -表面上被照射的位置处的法向量
Col –物体原表面颜色
AmbAmount -场景中环境光的强弱程度 (0 to 1)
Outputs:
SurfaceColor -环境光照,漫射光照与镜面光共同作用之后的表面颜色
DiffuseFactor = ... //经前两个光照作用得来的颜色
DirectionToViewer = Normalise(ViewPos - Pos);
VectorToLight = Normalise(LPos - Pos);
//计算反射光
ReflectanceRay = 2 * Dot(N, VectorToLight) * N - VectorToLight;
//计算镜面光照因子. 数学公式 SpecFac = (R dot N)^Spec
SpecularFactor = Pow(Dot(ReflectanceRay, DirectionToViewer), SpecAmount);
//环境光照,漫射光照与镜面光共同作用
SurfaceColor = Col*AmbFactor + Col*DiffuseFactor*LCol + SpecCol*SpecularFactor;
环境光照,漫射光照与镜面光共同作用
Note:可以在一个场景中使用多个漫射光照与镜面光作用
Fresnel Term 菲涅尔准则
菲涅尔效果是根据观察者的观察表面来调整反射率来实现的。比如你从水面,油漆表面或者丝绸的正上方看,反射光泽的柔和效果基本没有,如果侧着或平着看的话,反射光泽的柔和效果就很明显,这就是菲涅尔效果。我们简单地通过点积操作计算表明法线与视线之间夹角的余弦值,再将这个值加权。对于较平滑表面,加权系数设置在1.0-5.0之间(油漆效果,丝绸等),对于比较凹凸的表面,加权系数设置为8.0或更高(水波,液体等)
Inputs:
ViewPos – 观察者的位置
FresAmount – 边缘或表面的尖锐程度. (油漆丝绸:1,液体: 2-8)
FresCol - frenel 反射光 (通常使用reflection map or 类似的东西).
LCol – 照射在表面上的漫射光
Pos – 表面上被照射的位置
LPos – 漫射光源的位置
N -表面上被照射的位置处的法向量
Col –物体原表面颜色
AmbAmount -场景中环境光的强弱程度 (0 to 1)
Outputs:
SurfaceColor -环境光照,漫射光照与镜面光,菲涅尔反射共同作用之后的表面颜色
DiffuseFactor = ... //环境光照,漫射光照作用得来的颜色
SpecularFactor = ... //镜面高光作用得来的颜色
DirectionToViewer = Normalise(ViewPos - Pos);
//计算fresnel因子. 我们计算视线与表面法向量间夹角的余弦值(在[-1..1]之间),然后加一,移动到区间[0..2],然后再加权。
FresnelTerm = Pow(Dot(N, DirectionToViewer)+1, FresAmount);
//确保因子的在正常范围内
if (FresnelTerm > 1)
then FresnelTerm = 1;
//无菲涅尔反射的场合: Ambient light, Diffuse Light and Specular Light
NonReflective = Col*AmbFactor + Col*DiffuseFactor*LCol + SpecCol*SpecularFactor;
Reflective = FresCol;
//环境光照,漫射光照与镜面光,菲涅尔反射共同作用
SurfaceColor = NonReflective*(1-FresnelTerm) + Reflective*FresnelTerm;
漫射无菲涅尔反射时效果 漫射有菲涅尔反射时效果
各种光照的算法原理 菲涅尔法则相关推荐
- Unity Shader:实现菲涅尔+色散效果的环境映射以及相关原理解析
文章目录 1,色散在光学中的原理 2,反射的数学计算方法以及用它实现环境映射 3,折射的原理以及色散的实现 4,菲涅尔效果 5,拥有菲涅尔与色散效果的环境映射 1,色散在光学中的原理 复色光 --现实 ...
- Unity Shader:实现菲涅尔+色散效果以及相关原理解析
1,色散在光学中的原理 2,反射的原理以及环境映射的实现 3,折射的原理以及色散的实现 4,菲涅尔效果 5,将菲涅尔与色散效果增加到环境映射中 1,色散在光学中的原理 复色光 --现实生活中 ...
- UA OPTI512R 傅立叶光学导论18 亥姆霍兹方程与惠更斯-菲涅尔原理
UA OPTI512R 傅立叶光学导论18 亥姆霍兹方程与惠更斯-菲涅尔原理 亥姆霍兹方程 惠更斯-菲涅尔原理 亥姆霍兹方程 考虑source-free material (also linear, ...
- matlab 菲涅尔环,菲涅耳区讨论 - 通信原理与基础 - 通信人家园 - Powered by C114
1.菲涅耳区 当需要计算传播主区的几何尺寸时,要应用惠更斯-菲涅尔原理.惠更斯-菲涅尔原理认为,波在传播过程中,波面上的每一点都是一个进行二次辐射球面波(子波)的波源,而下一个波面,就是前一个波面所辐 ...
- 庄懂的TA笔记(九)<菲涅尔 + MatCap + CubeMap>
庄懂的TA笔记(九)<菲涅尔 + MatCap + CubeMap> 课程内容: 1.菲涅尔 0.效果展示.公式: 菲涅尔现象: Fresnel(菲涅尔) 用到的两个向量 NdirWS ...
- Three.js MeshStandardMaterial菲涅尔实现
前面两篇分别讲了Three.js的源码结构和Shader改写方法,本篇做一个基于Standard材质的菲涅尔. 如未读过前两篇的建议先读一下: Three.js Shader源码结构https://w ...
- Shader学习21——基于菲涅尔透明的扫描线
看到人家这样的一个效果,于是想自己也复制一个 Mar-26-2021 17-16-26.gif 想了一下思路,应该是菲涅尔的做的一个透明效果(单纯的菲涅尔透明可以看这篇),再去做了一个线的效果,线应该 ...
- Chango的数学Shader世界(七)水波模拟-透明水面,菲涅尔(Fresnel)效应
目的: 解析,改进,批评一个国外免费透明水面Shader,进一步了解Shader背后的物理原理. 参考: 菲涅尔反射 分析: 我将原水面Shader一再简化,从中抽取最主要的部分,忽略细枝末节,并改掉 ...
- Unity Shader 水多种元素的实现(反射、折射、菲涅尔、深浅、浪花/泡沫、水波、可交互)
综合效果 经过各元素叠加 和 程序的审美调参 后的综合效果 交互的水波与边缘浪花的合并需要优化一下 反射 两种方案: cubeMap 以水面对称设一个摄像机 cubeMap 实现:反射探针生成Cube ...
最新文章
- 你真的了解OKR吗?
- 举例说明html语言的结构,HTML语言的结构
- linux c++开发环境_使用 VM VirtualBox 搭建完善的Linux开发环境
- 华为云计算玉溪总经理_华为云计算(6)——FusionAccess
- 《视图更新与关系数据库理论》——2.1 关系和关系变量
- 时隔两年 重新当码农
- 位运算和进制转换,反码补码
- 单调栈 leetcode整理(三)
- linux下的磁盘配额简介暨 linux下加挂硬盘续
- [转载] Python中NumPy简介及使用举例
- Android 蓝牙开发(五)OPP接收文件
- ffmpeg (三):ffmpeg结合SDL2.0解码音频流
- c# async await异步方法
- sata7p 定义_纯正良品SATA7PTOSATA7P90度L250mm; CABLE;SATA线
- 【iOS 15】iPhone如何录屏?iPhone屏幕录制技巧分享
- Matlab学习笔记 kron函数
- PyTorch: Conv2d and ConvTranspose2d
- 解决cmd中文输入法看不到待选文字
- 学习操作系统,都有哪些硬核网站?
- 文献阅读:Improving neural networks by preventing co-adaptation of feature detectors
热门文章
- 《算法帝国》读后感(一)
- 5个 Word 小技巧,能够让你在制作和排版文档时如有神助
- Maven 命令下载pom.xml的所有依赖库
- 利用JS实现循环队列--击鼓传花游戏
- Spring Security入门篇——标签sec:authorize的使用
- 服务器硬件规格常用查看命令——网卡相关命令
- 前端歌谣的刷题之路-第一百二十六题-浮动
- 怎样消掉计算机桌面阴影,电脑桌面图标有蓝色阴影是怎么回事?怎么把它去掉...
- 【代码随想录二刷】Day23-二叉树-C++
- C语言实验九------心理测试试题