常用光照类型基本概念工作原理及其计算公式

iefreer 发表于 2018-11-16 15:09:01

标签: webgl, light, color

- +

在三维场景中,原理上物体的渲染效果取决于光照与物体表面的相互作用,对于渲染程序而言,可以通过把一些数学公式应用于像素着色来实现,从而模拟出真实生活中的各种材质效果。比如金属、玻璃、木质或石刻效果等。


本文做如下假定:


  • 我们讨论的是基于像素着色(per-pixel basis),每个pixel有它自己的位置向量,法线向量以及表面颜色(Surface color,在这里可以是来自纹理的颜色,也可以是RGB颜色(flat color));

  • 表面颜色(Surface color)通常是由R,G,B三部分组成,在这个教程中,我们把它当作一个向量看待;

  • 输入表面颜色(光照处理前的表面颜色,这里的“输入”可以理解为函数的输入参数的“输入”)只是普通的颜色(单纯的纹理颜色或者RGB颜色),而输出表面颜色(光照处理后的表面颜色)是光照作用于表面的合成颜色,如可以是有阴影,高光等效果的颜色。

  • 这个教程中假设每个场景中只有一个灯光。对于多灯光的场合,对每一个灯光循环进行这些运算(环境光除外)。


Ambient Lighting 环境光

在真实生活里,有光源的房子里的物体不会是全黑的,即使这个表面是背对光源的,这是因为有环境光(可看作是光线在环境中经过充分传播后所形成的一种无方向的全局均匀光照)。我们认为场景中的物体,不论它在什么位置,总会受到一定数量的环境光照射。环境光照算法如下:


输入输出

Col – 物体原表面颜色

AmbAmount – 场景中环境光的强弱程度 (介于0 到 1之间)

SurfaceColor – 环境光照作用之后的表面颜色

SurfaceColor = Col*AmbAmount


环境光照效果图:

 ambient.png

Lambert Shading 漫射光

现在我们真正开始考虑一束光照射在物体表面上的作用过程,我们使用最常见的光照算法-------漫反射光照着色(或者说郎伯特余弦定律或郎伯特着色),这个算法是将入射光与表面法线向量的点积当作漫反射光照强度因子,下面我们看看环境光照与漫射光照共同作用的算法:

输入输出

LCol – 照射在表面上的漫射光

Pos – 表面上被照射的位置

LPos – 漫射光源的位置

N -表面上被照射的位置处的法向量

Col –物体原表面颜色

AmbAmount -场景中环境光的强弱程度 (0 to 1)

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;


环境光与漫射光共同作用效果

 diffuse.png

Specular Highlights 镜面高光

现在我们考虑物体表面有光泽的效果,这种效果是将Phong反射模型,结合前面两个光照作用而成。这中光照效果计算需要知道观察者在场景中的位置,而先前的环境光照与漫射光照效果计算都与观察者所在位置无关的。


这种光照计算是这样的,首先我们计算入射光在表面处的反射光线,然后再将反射光线与视线(观察者的眼睛与表面观察点的连线)之间的点积值当作反射到观察者眼中的光照强度因子,因为表面上高亮的部分是反射光线反射到观察者眼睛或照相机中较多的地方,这些地方的反射光线与视线之间的夹角非常小,点积值就越大。

输入输出

ViewPos – 观察者的位置

SpecAmount – 镜面光强弱. (from 0 to about 200)

SpecCol – 镜面光颜色(通常为白色).

LCol – 照射在表面上的漫射光

Pos – 表面上被照射的位置

LPos – 漫射光源的位置

N -表面上被照射的位置处的法向量

Col –物体原表面颜色

AmbAmount -场景中环境光的强弱程度 (0 to 1)

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;


环境光照,漫射光照与镜面光共同作用

specular.png

[ 注意:可以在一个场景中使用多个漫射光照与镜面光作用 ]

Fresnel Term 菲涅尔准则

菲涅尔效果是根据观察者的观察表面来调整反射率来实现的。比如你从水面,油漆表面或者丝绸的正上方看,反射光泽的柔和效果基本没有,如果侧着或平着看的话,反射光泽的柔和效果就很明显,这就是菲涅尔效果。我们简单地通过点积操作计算表明法线与视线之间夹角的余弦值,再将这个值加权。对于较平滑表面,加权系数设置在1.0-5.0之间(油漆效果,丝绸等),对于比较凹凸的表面,加权系数设置为8.0或更高(水波,液体等)

输入输出

ViewPos – 观察者的位置

FresAmount – 边缘或表面的尖锐程度. (油漆丝绸:1,液体: 2-8)

FresCol - frenel 反射光 (通常使用reflection map or 类似的东西).

LCol – 照射在表面上的漫射光

Pos – 表面上被照射的位置

LPos – 漫射光源的位置

N -表面上被照射的位置处的法向量

Col –物体原表面颜色

AmbAmount -场景中环境光的强弱程度 (0 to 1

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;


 diffuse2.png

漫射无菲涅尔反射时效果                    

fresnel.png

漫射有菲涅尔反射时效果


possitive(2) negative(0) views1646 comments2
私信 收藏 分享
分享到

发送私信

最新评论

iefreer 2018-11-16 15:51:26

菲涅尔方程推导说明:https://www.brown.edu/research/labs/mittleman/sites/brown.edu.research.labs.mittleman/files/uploads/lecture13_0.pdf


iefreer 2018-11-16 15:37:37

https://en.wikipedia.org/wiki/Fresnel_equations


请先 登录 再评论.
相关文章
  • 2019年开源WebRTC媒体服务器选型比较

    什么是WebRTC服务器?在WebRTC的早期开始,该技术的主要卖点之一是它允许点对点(浏览器到浏览器)通信,几乎没有服务器的干预,服务器通常仅用于信令(比如用于...

  • 增强现实引擎ARToolKit工作原理简介

    ARToolkit是一个基于CV(计算机视觉)和Marker(标识)的开源增强现实引擎。其具备如下功能特性:A. 鲁棒跟踪,包括基于标记的跟踪与基于特征的跟踪;

  • 踏得网精选2016年度10大最佳HTML5动画

    踏得网精选2016年度最酷最新的HTML5动画集,评选标准为:创意新颖度+实现技术难度+趣味程度。使用一些在线H5生成工具的作品,因其主要使用图片和CSS3套路动画,...

  • 使用HTML5 FileReader和Canvas压缩用户上传的图片

    手机用户拍的照片通常会有2M以上,这对服务器带宽产生较大压力。因此在某些应用下(对图片要求不那么高)我们可以在客户端来压缩图片,然后再提交给服务器。总体...

  • HTML5、Hybrid APP、Native APP对比和技术选型

    HTML5和Native APP都很容易理解。为了获得HTML5的移植性和移动本地应用的高性能,搞出来一些混合APP的解决方案。比如Apache的Cordova(也就是以前的PhoneGap),...

  • 学习使用CSS制作进度条

    进度条是基础的界面控件,可用于多种场合,比如任务完成进度,手机充电状态等。本文介绍一个简单实用的进度条制作方法。预期效果如下图所示:直观上,我们可以把该进度条控件分为2个部分,外部的边界用来表示固定的目标范围,里面的条形部分用来表示当前进度。外部目标范围元素的CSS代码编写如下:.pb-scope

  • 三维向量的简单运算和实用意义

    在WebGL的实际应用中我们广泛使用向量的几何运算来计算角度、距离,判断点线、点面之间的关系,比如物体之间的碰撞检测。本文简要介绍三维计算机图形学中常用的...

  • 纹理基础知识和过滤模式详解

    1、 为什么在纹理采样时需要texture filter(纹理过滤)。
    我们的纹理是要贴到三维图形表面的,而三维图形上的pixel中心和纹理上的texel中心并不一至(pixe...

  • WebGL 纹理映射模式以及WRAP_S | WRAP_T参数详解

    我们在纹理滤镜一文中已经说明了2个重要的纹理参数,用来定义对象缩放时纹理的处理方式:GL_TEXTURE_MIN_FILTERGL_TEXTURE_MAG_FILTER本文讲解其余几个纹理参数...

  • D3.js读取外部json数据

    D3.js是一个很好的数据可视化工具,支持从web服务读取json数据,或者从外部文件如.json, .csv文件中直接读取。由于部分服务比如flickrs上的图文数据服务需要VPN...

  • Three.js 开发基础知识 - 绘制3D对象

    Three.js是一个用来简化WebGL开发的JavaScript库,比如绘制一个三维立方体,使用WebGL需要100多行,那Three.js只要10几行就能够完成。本文通过创建一个立方体来...

  • Three.js 3D打印数据模型文件(.STL)加载

    3D打印是当下和未来10年产品技术主流方向之一,影响深远。对于电子商务类的3D打印网站,一个主要功能是把商品以3D的方式呈现出来,也就是3D数据可视化技术。HTML...

  • inline-block元素设置overflow:hidden属性导致相邻行内元素向下偏移

    在表单修改界面中常会使用一个标签、一个内容加一个修改按钮来组成单行界面,如图1所示。那么在表单总长度受限的情况下,当中间的邮箱名称过长时,会遮盖到旁边...

  • 如何使用CSS3实现书页(书本)卷角效果

    我们有时候想在页面显示一个公告或用户提示信息。一个常用设计是使用书签形状。我们可以给书签添加卷角效果,以使其更为逼真。所谓的“卷角”实际上可以用小角度...

  • 如何使用纯CSS3实现一个3D泡沫

    要实现一个逼真的泡沫,涉及到比较复杂的光学/物理学知识。我们这里先简化下问题,实现一个相对简单而足够实用的泡沫元素。我们可以把基础的泡沫元素应用在很多场景中,比如水景、泡咖啡、啤酒甚至火焰特效中。泡沫首先是一个圆形元素.bubble

  • 更多...