type
status
date
slug
summary
tags
category
icon
password
众嗦粥汁,一个物体呈现什么颜色是因为它吸收了一部分的光,并反射出一部分的光。
因此定义光线lightColor,和物体光线toyColor,两者相乘就可以得到物体被光照射之后产生的结果了。
介绍完颜色,后面将使用Phong Lighting Model实现光照

Blinn-Phong光照模型

这一光照模型将光分解成环境光、漫反射光和高光。

环境光

光从光源发出并反弹,一个场景中通常不止有一个光源。现在对于这种场景中光源的处理通常采用全局照明算法,但是它的开销很大并且非常复杂。而环境光照是一个简化的全局照明模型,通过一个常量环境因子乘以光的颜色再乘以物体颜色可以得到。

漫反射光照

漫反射即光线照射到物体上之后向四面八方反射,从各个角度都可以看到。但是漫反射的效果跟光的衰减、入射角度、光的颜色和物体颜色有关。因此可以得到漫反射项应该是这样的
这里的FragPos是像素位置,可以根据顶点着色器中输入的顶点位置加上模型变换矩阵(mvp中的m)得到。至于法向量这里是这么计算的
这个法线矩阵将输入的法线根据模型变换矩阵求逆再转置去掉位置信息后得到。矩阵求逆的运算应该在CPU中完成,它在GPU上的运算是非常耗时的。

高光

高光的产生是因为光在物体上发生镜面反射,反射的光线进入眼睛产生的。它不像漫反射向四面八方反射,因此高光需要在漫反射的基础上算出出射方向可以得到。
OpenGL提供的reflect函数第一个参数是入射方向,第二个参数是法向量,根据这两个向量可以得到出射方向,但是这样的开销很大。Blinn-Phong模型改进的地方就是这里。这里通过求出入射光线和光差方向的半程向量,比较半程向量和法向量的角度得到结果。shininess是物体的反光度,这可以反映这个物体是金属还是塑料的,金属材质的物体反光度更高。
最后加载将三者加在一起乘以物体的颜色得到Blinn-Phong光照模型的结果。
notion image

材质

上面的环境光、漫反射、高光等信息通常可以用来描述一个物体的材质。各种不同物体的材质都有一个比较准确的记录的数值,可以在这里找到。
它通过定义物体本身的对光照模型中三项不同的反射数值和反光度来让物体呈现出类似于金子、珍珠、塑料等效果。
定义了物体的数值还要定义光的一些数值,比如环境光会被反射多少,高光又会被反射多少等,这里直接用一个float来统一概括rgb各项的反射强度。
再将这些数据结合起来
珍珠
notion image
 
黄金
notion image
 
红色塑料
notion image
三者除了颜色能看出一定的差别。
 
通常在游戏中一个物体不可能由单一的一种物质组成,比如上面的几种。如果需要在场景里面渲染一个小车,通常需要它的轮胎的材质、玻璃的材质、车身钢板的材质等等,因此这些都会交给纹理去完成。
通常环境光可以使用漫反射贴图去完成。而高光贴图是一张灰度图,比如下面的木头不应该出现高光,所以它的灰度应该是vec3(0.0f).而边缘的钢铁材质的物体应该出现一定的高光那么灰度就会是vec3(0.5f)左右。在这个灰度图里面,像素越白证明反射的的效果越明显。
下面是使用光照贴图去的效果
notion image
以上的光都是点光源接下来会讲一些其他类型的光源

平行光

平行光只有方向信息,它被认为是无限远的光固定往某个方向不断投射过来的。
当然,其实可以继续使用点光源的结构体,将位置信息用vec4存储,第四个分量为0的时候说明这个信息存储的是位置,否则说明这个信息存储的是方向
可以看到加了平行光后物体没被点光源照射到的地方更亮了
notion image
用颜色区别一下平行光
notion image

衰减

在进入聚光之前先看一下衰减。
光线离得越远,光的强度应该越低,现在点光源不真实的原因有一部分是因为前面并没有考虑光衰减的因素。
这是光照的距离的计算公式
在不同光能照射的距离下,常数项、一次项和二次项的值是不同的,这里提供了光不同范围下的值。
这里采用光照射范围为50下的情况

聚光

notion image
聚光和手电筒类似,如果所在像素在照射的范围内,那么说明这里应该被手电筒照亮。计算手电筒位置到像素点的方向和手电筒方向的夹角即可,如果超过了范围就处理手电筒光照,否则就不做处理或者做手电筒的环境光处理
做出来以下效果
notion image
但是正常来说手电筒边界不应该是这么分明的,这里需要做一个边缘软化的处理。
可以将手电筒看作一个圆锥,圆锥上由两条边界线,从椎顶到第一条边界是照亮的,第二条边界到锥底是不被照亮,是暗的,在两条边界之间是从照亮到没被照亮之间过渡。公式是这样的
theta表示当前的角度,gamma表示第二条边界的角度,epsilon是这两个边界的差
可以得到以下效果
notion image
 
[OpenGL]批量渲染Batch Rendering[OpenGL]使用纹理
Loading...