GAMES101现代计算机图形学入门——着色Shading(笔记+部分概念解析)

着色(Shading)

着色就是对于图像引入不同的明暗和颜色差异,在图形学上理解为对不同的物体应用不同的材质的过程。

简单着色模型 (Blinn-Phong)

高光 + 漫反射 + 环境光

  • 高光:由于光源直射导致的反射
  • 漫反射:由于光源直射导致的向多个方向的反射
  • 环境光:由于其他物体反射光源导致的光照反射
    在这里插入图片描述

定义对于某个shading point在物体表面上

  • n为法线
  • 光线照射方向是I
  • 观测方向为v
  • 定义一些关于物体表面的属性,如color、shininess等
  • 这些向量都定义为单位向量,因为仅表示方向

对于物体的局部着色,不考虑其他物体的阴影,而不考虑其他物体的遮挡等

漫反射(Diffuse Reflection)

一个直射的光线被反射到各个方向,可能存在很多问题;

漫反射的强度可以看作被照射物体接收到了多少能量,这和物体表面和照射光线的夹角有关,一般根据一个像素点周围的单位面积接收到的光线强度计算

在这里插入图片描述

兰伯特Lambert’s余弦定律: 光照方向和物体表面的法线方向的余弦成正比,预先越大表示反射越强,越小表示反射越弱;如法线和光强照射方向一致则反射最强

点光源Light Falloff:认为在任何时刻,一个点光源发出的能量集中在以点光源为球心的球壳上,并且在远处的球壳和近处的球壳上能量是相同的(因为远处的球壳的能量是近处传播过去的);所以在离点光源越远的地方,球壳单位面积上光强就更低,即某个位置的光强和距离点光源的位置成反比;所以,计算shading point的光强,需要根据其离点光源的距离来计算
在这里插入图片描述

Lambertian Diffuse Shading

在这里插入图片描述
通过计算漫反射系数,由点光源强度和点光源到达反射表面的距离计算得到的在反射点的光强,以及由反射表面法向量和光照方向向量(均为单位向量)相乘得到的反射夹角余弦值得到反射光强的多少,就可以得到最终漫反射的光强

所以,漫反射和观察角度完全无关,只考虑光照方向和反射表面的夹角

漫反射系数用来定义表面的反射程度,越高代表反射程度越高

高光反射(Specular Term)

反射非常接近镜面反射方向,反射强度依赖于观测方向和镜面反射方向,当观测方向和镜面反射相近时就可以看到反射。

观察方向和镜面反射方向接近 <==> 半程向量和法线相近,半程向量是指光线入射方向和观测方向两向量的之和的单位向量,而衡量是否相近的方法即cosα的大小,对于两个单位向量来说即两单位向量的乘积;
在这里插入图片描述

所以,在设定反射系数后,结合光强在球壳上的分布(距离光源的距离)以及法线和半程向量的夹角余弦值即可计算反射的结果光强;

如果使用镜面反射向量和观察发现来计算,则称之为Phong模型,是Blinn-Phong的前身,其计算比直接计算法线和半程向量复杂;

在夹角余弦这里有一个指数p,这是因为cos的导数较缓,使得即使偏移角度很大,对高光的减弱仍然较低(可以看到高光的角度范围较大);所以,可以加上指数,使其下降到趋近零的速度更快,一般可以将p设置超过64,甚至128

环境光(Ambient Term)

假设环境光是来自于四面八方的,而且是强度相同的,此时环境光即不考虑入射光线角度,也不考虑观测角度;如果这样考虑,则环境光就是一种颜色,保证某些区域不是黑色的。

此时,只需要设置环境光系数和环境光强度就可以得到一个常数的环境光反射。
在这里插入图片描述

Blinn-Phong反射模型

当我们将上述的三种反射加在一起,就可以得到最终的反射模型

在这里插入图片描述

着色频率(Shading Frequencies)

着色频率就是说,应该把着色的方法运用在哪些地方,如对每个平面计算着色,或者对顶点进行计算着色再使用插值的方式着色三角形,也可以对每一个像素进行着色;

平面着色(Shade each triangle / flat shading: 对三角形的平面,使用两边叉积求出法线,根据着色算法计算出结果后,直接对三角形进行着色

顶点着色(Gouraud shading): 在任意一个顶点上求出法线,对每个顶点进行着色,对顶点间三角形内部的颜色进行插值着色;

像素着色(Phong Shading): 对于每一个像素进行一次着色计算;

这三种着色频率在模型面数较少的情况下,复杂的着色频率效果更好、效率越低;但如果模型面数较多的情况下,使用简单的着色频率也不一定比复杂的着色频率效果差;具体需要根据模型的面数决定。

定义顶点的法向量: 对于任何一个顶点,其一定和很多三角形相连;当求一个顶点的法线时,只需要将其相连的三角形的面的法线求平均即可得到顶点的法线;但因为三角形的面积各不相同,所以求平均时也可能加上一些权重;
在这里插入图片描述

定义像素的法线: 在两个点之间进行插值计算,具体见下节

图形管线(实时渲染管线)Real-time Rending Pipeline

管线表示的时一系列图形处理算法和流程,直到最终生成一张最终的图像的过程。

首先定义三位空间中的顶点以及哪些顶点可以形成三角形,再进行投影到平面以及光栅化和深度缓存到实际的像素上,进行着色后就可以得到一张图像。

在这里插入图片描述

在现代GPU中,其中的大部分流程是硬件编程的,也允许其中的某些流程进行可编程的客制化。比如可以自定义顶点和像素是如何着色的,可以使用opengl等api;

而shader是对每一个顶点或像素都执行的,只需要写好一次着色器即可,如顶点着色器、像素着色器或者片段着色器;

着色器

  • 几何着色器
  • 计算着色器:可以做几乎任何形式的计算

纹理映射(Texture Mapping)

有时,对于同一个模型,需要在物体表面不同位置的点定义不同的属性;
在这里插入图片描述

**表面:**对于一个三位物体,其表面是可以展开成为一张二维图片的;如果将一张对应的贴图贴在模型上,就可以定义模型表面每个位置的属性;对于三角形上的每个顶点,都需要规定在纹理上的坐标。

纹理上的坐标系通常使用一个二维坐标系,两个轴分别为u-v,模型的每个顶点可以使用对应在该坐标系的值来获取对应的纹理属性。通常都认为u、v的范围是0-1范围内的;

纹理是可以使用多次的,如果纹理设计较好,其可以在四个方向连续使用同一纹理时达到无缝衔接的效果。

在三角形内部进行插值(重心坐标)

由于很多着色是在顶点上操作的,而我们希望在三角形内部得到一个平滑的过度,使得每个顶点之间的过渡都是自然的;通过三角形的顶点得到的纹理中的位置,但也需要得到三角形内部关于纹理的位置映射;所以我们需要插值计算。

重心坐标(Barycentric Coordinates)

重心坐标是定义是在一个特定的三角形上的。在三角形ABC所形成平面内的任何一个点,都可以表示成ABC三个点坐标的线性组合。只需要满足α、β,γ的和为1即可。
但如果这个点在三角形内部,则α、β,γ必须都大于0。

在这里插入图片描述

每个顶点对应的参数和其不相邻的、被三角形内部点与三角形顶点连线形成的三个三角形之一的面积有关,如下图,即三个参数可以可以通过面积比得到。

在这里插入图片描述
由此,可以得到三角形的重心,三角形的重心将三角形分为等面积的三份。

在这里插入图片描述

所以,我们可以根据下列公式计算出三角形内任意点使用三角形顶点表示方法

在这里插入图片描述

当得到上述公式后,在对三角形内部的值进行插值时,我们应该使用得到的α、β,γ来线性组合三角形顶点对应的属性
在这里插入图片描述

但是,在三位空间中的三角形投影变换后,不能保证重心坐标不变。所以,如果需要投影三位空间中的三角形,必须要在三维空间中计算重心坐标,而不是在投影后的三角形中计算;比如,计算深度插值一定不能在投影后的三角形做。

应用纹理

对于屏幕上任何一个采样点,都可以通过插值计算出其在纹理上的u-v坐标,所以就可以从纹理中取出一些属性,如颜色、漫反射系数等

在这里插入图片描述

纹理放大

如果一个纹理和实际渲染的图片相对较小(如分辨率不同),可能在纹理上取到的一些值不是整数;

如果采样点对应的纹理坐标不是整数,那么就需要对非整数坐标进行处理;

简单案例

对一个像素(pixel),其在纹理上取得的一个纹理元素(texel);在像素对应的纹理元素需要被近似处理,如使用四舍五入选择最近的坐标、双线性插值或双三次插值
在这里插入图片描述

双线性插值: 对于一个像素,其映射到了纹理上一个非整数的点,对于该点对应的纹理,可以进行一些操作;

  1. 找到这个坐标在纹理上临近的四个点
  2. 使用线性插值:对应两个离散的点,与两点在同一直线上的点可以用该直线的方程来进行插值计算
  3. 首先利用横向的两组点,计算目标点在一个方向上的插值,再利用这两个插值来计算另一个方向上的插值

在这里插入图片描述

双三次插值: 使用周围的16个点,进行多次4个一组的插值,但计算量较大

复杂案例

因为屏幕上像素覆盖实际纹理大小是各不相同的,近处覆盖的纹理较少,而远处覆盖的纹理较多;近处像素可以使用近似的采样方法,因为其覆盖纹理少,较少的纹理就可以表示像素了;但远处的像素可能覆盖了过多纹理,使得很难使用采样来选择适合的纹理来代表像素。

在这里插入图片描述
在这里插入图片描述

解决方法中,最简单的是使用超采样技术,如果将每个像素分成多点采样,再在纹理上计算,就可以得到很好的结果,但性能消耗也很大;

实际上,如果避免采样,只要在任何区域内计算得到该区域内纹理的平均值,就不会产生这个问题;这实际上是一个点查询到范围查询的转换;

Mipmap: 这是一种快速近似的矩形范围查询;Mipmap的本质实际上是使用一个图生成多个分辨率更低的图,这些图是通过平均算法得到的;

  • 每次生成的图是前一张生成图的四分之一大小

  • 根据等比数列求和,得到的最终的存储大小只比原图多了三分之一

在这里插入图片描述

  • 另一个问题是,像素覆盖的纹理区域是如何得到的?

    • 首先,取像素自己的中心和相邻上右两像素的中心投影到纹理上
      在这里插入图片描述
    • 将这个像素覆盖的区域近似成为一个正方形,计算方法为计算这个像素与相邻两个像素在纹理上投影后,该像素投影与其他两个投影在纹理上的距离,并取最大值作为近似覆盖纹理矩形区域的边长;
      在这里插入图片描述
  • 得到覆盖的区域之后,需要根据这个区域的大小来寻找Mipmap中对应那一层图的哪一块区域;需要寻找的图的层级即为D;覆盖区域越大,就越需要去越高层的Mipmap查询;

    • 但是,也可能存储某些覆盖的区域大小不能完美契合原本的Mipmap层级大小,可能在两个Mipmap单位大小之间;此时,需要对相邻的两个Mipmap都做双线性插值,然后在对这两个插值结果再做一次线性插值,这样就完成了三线性插值;

      但是在Mipmap中是不需要进行真正的插值的,只需要进行查询即可得到结果,所以实际上只进行了一次插值。

    在这里插入图片描述

  • 但是对应Mipmap,它可能会忽略掉远处所有的细节,导致和超采样得到的结果差距很大,这是一种过度模糊现象;这是因为Mipmap的计算实际上是进行了对角线方向的压缩,但是实际上可能水平和竖直方向的压缩是不均匀的。

    在这里插入图片描述

    • 为了部分解决这个问题,可以使用各向异性过滤

各向异性过滤: 可以查看轴向对齐的矩形区域而不只是正方形区域,这样可以得到不同长款比例下的纹理缩放图,对于矩形的查询相比正方形的Mipmap查询结果会更准确,但对于不规则区域的查询任然有很大的问题。并取存储开销会成为原来的三倍。各向异性的倍数是用来计算Ripmap两个方向压缩的层数的,但无论开多少倍,都会收缩到原来存储的三倍左右,所以如果显存足够完全可以将各向异性过滤使用最高档位。

EWA过滤:对于任意不规则的形状,可以拆分成圆形来覆盖这个形状,只需要多次查询就可以覆盖这个区域,但查询可能会造成性能损耗
在这里插入图片描述

纹理的应用

纹理可以有很多应用,简单理解成纹理就是一块内存,可以做点查询和范围查询以及过滤等;所以,纹理实际上可以表示的东西非常多,如环境光贴图,凹凸贴图等;纹理可以定义表面上的任何属性。

环境光

把任何方向上了照射光线通过贴图的方式记录下来,从而直接在着色的时候使用这些环境光贴图;并取使用环境光贴图会假设所有环境光来自无限远处,认为所有光线都是无限远;

存储环境光可以存储在一个球体上,并取可以展开球面来记录该点对应的全部环境光;只需要假设有一个镜面的球或一个鱼眼摄像机,就可以将环境中所有光记录成一个球;

但是这样做,可能会导致球面展开图会导致扭曲,这是因为球面展开时都会在极端出现扭曲;解决方法时将球体外设置一个包围盒,让这些各自方向的光线照射到正方体包围盒上,从而让环境光信息存储到立方体上,这样的话展开立方体成六面不会产生扭曲;
在这里插入图片描述

但是,如果存储在球上,就可以通过极坐标方向来快速找到某个方向的光照,但是如果存储在立方体上就需要先判断存储在立方体的哪个面,在找到这个方向光线的信息。

凹凸贴图

纹理也可以描述表面的凹凸状况,使得几何形体不必通过大量的三角形来定义表面凹凸状况,而是通过一个复杂的纹理来定义某些点相对的高度;相对高度可以用来使得法线发生变化,而导致着色发生变化,从而产生了明暗的对比。

在这里插入图片描述

通过法线贴图,可以定义一个复杂的纹理,不改变几何形体;法线贴图可以对每个像素的法线做出扰动,即定义了任何一个点相对位置的增减,使得点对应的高度在计算时被认为发生了一定的改变,使得法线也发生了一定的变化。

在这里插入图片描述

对于一个二维的凹凸贴图,可以求出某个点法线坐标,通过计算相邻两点间高度差,使用高度差除以两点间距(为1)计算得到某个点的切线,而计算切线的法线只需要将切线旋转90°(公式为对换x、y,并给x加负号)再进行归一化即可。其中c只是一个参数。

在这里插入图片描述

对于三位的凹凸贴图,则需要计算目标点在u,v两个方向的切线(同样使用高度差除以u、v方向的距离1),同样计算这个切线是垂直切平面的,得到归一化的切线得到单位向量即可。

注意,这里计算时,定义了一个局部坐标系,定义了法线的坐标系。详细可以看官网对应问题3的解答。

在这里插入图片描述

位移贴图

该纹理仍然是一个纹理,但位移贴图是会实际上改变顶点的几何位置;使用凹凸贴图时,在模型边缘会不够真实,以及自身的突起不会投影到自身;

位移贴图的要求是,模型的三角形要足够细致,一般要求三角形的间隔低于位移贴图纹理定义的频率;也可以在初始时使用一个较粗糙的模型,在应用位移贴图的过程中,如果需要拆分三角形则可以细化三角形,这就是动态曲面细分方法(DirectX);

三维纹理

实际上,纹理也可以定义为三维,表示空间中任意一个点对应的属性;在空间中只需要定义一个噪声的函数,根据一系列的计算得到空间中点的属性;比如可以设定大理石花纹和山脉起伏;

提供阴影预计算

也可以记录一些之前已经算好的信息,如可以记录一些在计算环境光时无法记录的信息;这种时候可以使用环境光遮蔽(ambient occlusion)技术,也可以计算处一个环境光遮蔽纹理乘以着色结果来提前进行计算。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值