games101学习笔记_shading1(着色)

可视性 / 遮挡(Visibility / occlusion)

画家算法(Painter 's Algorithm)

画家算法的提出主要是为了实现深度缓冲.
画家在画油画时,总是会从远景开始画,然后逐渐画近景覆盖远景,比如下图:最先画出一个蓝色的山,然后接着画绿地覆盖蓝色的闪,然后再接着画上几棵树覆盖绿地。作画顺序
比如我们想要画一个正方体:
正方体
先画出最后面的面,然后再画上面和右面,最后画正面。就可以得到这样一个正方体。先画背面最后画正面可以理解,那么四个侧面的顺序是如何决定的?目前我们只是暂时用这种画法,没有什么特殊的决定方法。但是若更改一下顺序,先画上面和左面,再画右面和底面,就会导致右面有一条线无法被覆盖,立方体的上面就会多出一条线。

按照画家算法的思想,要先对三角形的深度进行排序(O(nlogn)),排完序之后再按照从深到浅的顺序画三角形。但是这样实际应用的时候就会有问题,如下图:
环路
这种情况下,我们无法对这三个三角形按照深度进行排序。
针对这个问题,在之后又提出了另外一种解决方法。

深度缓冲(Z-Buffer/Depth Buffer)

Z-Buffer的想法是不再对物体做远近排序,而是对每个像素做排序。
简单来说就是2D屏幕上的每个像素都记录两个缓存值。
在这里插入图片描述
这两个值分别是:

  • 该像素所对应的3D物体的最小的Z轴坐标值,即对应像素的Z轴坐标。 详细来举例就是:比如说鼠标放在画面中的一个位置上,这个位置刚好是一个像素,在我们没有画出三角形之前,这个像素点是在地板上的,此时的像素点存的就是地板像素的深度值,但等我们画出正方体后,这个像素点又对应了正方体上的像素,此时正方体像素的深度值和地板像素的深度值比较,是正方体的深度值小,意味着在同一个像素上正方体会遮挡住地板,所以更新这个像素点的深度值,将其变为更小的深度信息。这个也叫做depth buffer 深度缓存,即存储每个像素点对应的深度信息 (深度图)
  • 对应Z轴坐标的3D物体的颜色信息,即地面的绿颜色。 这个也叫作frame buffer,即存储每个像素点对应的颜色信息,这个buffer其实就是最后生成的图片 (最后结果)
    在这里插入图片描述
    在这里有一个需要注意的问题: 之前的内容,我们始终假设相机位于原点,且朝着Z轴负方向,所以离相机越近,Z轴坐标绝对值越小,反之越大。这里为了方便起见(仅讨论深度问题),所以假设Z值永远是正数,即Z越小,表示越近;反之越远。

在这里插入图片描述
在上图右,我们可以看到,离我们越近在图片中就显示地越黑,离我们越远显示地就越白。

为了实现Z-Buffer,图形学中通常采用的做法是:在渲染最后成品图的同时,也会同时生成另外一个深度图像,这个深度图像只存储了任何一个像素它所看到的几何物体中最浅的深度信息。

Z-Buffer算法伪代码实现

初始化所有的深度为无限大。
在光栅化的时候:

for (each triangle T)	//对于任意一个三角形
		for (each sample (x,y,z) in T)	//都可以将其光栅化成不同的像素			
			if (z < zbuffer[x,y])  //如果当前的深度缓存值小于之前记录的深度缓存值			
				framebuffer[x,y] = rgb; 	//update color更新颜色值				
				zbuffer[x,y] = z;   //update depth更新深度值
			else
				// do nothing, this sample is occluded
				//什么都不做,这个采样点被遮挡
				;  

在这里插入图片描述
上面仅代表深度图,而不是最后的成品图,其中R代表无限大。
在深度值小于像素一开始的深度值(无限大或已经有值),就覆盖(替换)这个值,否则不变。

Z-Buffer复杂度

复杂度:

  • 对于n个三角形是O(n)的复杂度(因为没有进行排序,所以这个复杂不可能解决遮挡问题)。

注意: 由于在计算机里,深度值一般都是由浮点数表示的,所以理论上来说3D物体的深度值是不会相等的 。但是当对深度值做近似处理的时候,比如取整,这个时候两个像素的深度值就一样了

着色(Shading)

  • 模型变换(Model Transformation):即咱们先把机器人摆成我们要的某种pose,摄像机也放在真实世界某个位置。
  • 视图变换 (View Transformation):把相机始终放在(0,0,0)位置,然后计算物体相对于相机的坐标位置。(其实相机拍的是机器人正面,为了方便理解才没有把机器人侧着画)
  • 3D位置信息确定好了之后,我们就需要做投影变换,即把3D映射到2D。
  • 得到2D位置信息后,我们需要做光栅化,即确定具体的像素位置。
    目前能做到的
    如果不做着色处理,那我们能得到的是下图:
    能做到的
    如果做了着色处理就会得到我们想要的效果:
    我们希望的

着色的定义

对不同的物体用不同的材质进行着色。

一个简单的着色模型(Blinn - Phong Relectance Model)

在这里插入图片描述

  • 可以看到茶杯上有一个高光(Specular highlights)
  • 茶杯表面除了高光外,其余地方颜色变化并不剧烈。我们将其称为漫反射(Diffuse reflection),除了茶杯,墙面的表现效果也是漫反射。
  • 图中的光源是从右上角照射过来,在茶杯的背面应该看不到这个光源,既然如此茶杯的背面应该是黑色。但是我们看到了这个茶杯的背面并不是黑色,也就是说有一些的光从茶杯的背面反射到了我们的眼里,那么这个点一定是接受到了光。但是这个点接受到的并不是直接光照,假如说任何一个点都能够接收到来自环境的反射光,这个反射光就是环境光照(Ambient lighting)。

着色是局部的(Shading is Local)

计算某一着色点的光照

在这里插入图片描述

  • v——观察者方向(view direction),着色点到相机的方向
  • n——表面法向量(法线)(surface normal),垂直着色点的反向
  • l——光的方向(light direction),着色点到光的方向
  • 表面参数(surface parameters): color,shininess(比如光的亮度)

注意: 起点也是着色点,而不是光源,这是一种约定俗成的规定,也是对编程模型的预约定,这样可以不引入光源数据结构,只从着色点出发做处理,这样会简便很多。同时,以上定义的向量都是单位向量

下图是一个着色的例子,这个材质球按理来说应该会在地面上有一个投影,但在下图中并没有。前面提到起点也是着色点,而不是光源,对于地板自身来说,它自身就是着色点,而且这里也只单纯考虑着色而不考虑其他因素的存在(比如该着色点是否会被阴影挡住,这种情况我们并不考虑)。所以得出的结论是着色 ≠ 阴影(shading ≠ shadow)
着色的材质球

漫反射(Diffuse Reflection)

  • 光打到一个点上,接着光被均匀地散射到所有的方向。
    • 表面颜色对于所有观察方向都是相同的。

在这里插入图片描述

被接受到的光

同样的光,打到相同的物体表面上,不同的光照射的角度不一样,造成的明暗效果也不一样。

射出去的光(能量)有多少是能被接收到的?
下图是兰伯特余弦定律(Lambert’s cosine law)
在这里插入图片描述
结论:漫反射效果,即着色点单位面积上接收到的光照能量强度 ,与着色点法线和光线之间的夹角成反比,着色点法线与光照方向平行时,接受到的光能量越大。cos θ = l(向量)·n(向量)

光衰减(Light Falloff)

下面介绍了光衰减的原理。中心点是光源,我们假设光在传播过程中能量没有损失,也就是说以该光源为球心的所有球面能量都是一样的。
在这里插入图片描述
我们假设半径为 r 的球面的能量是 E。由于我们假设光在传播过程总能量没有损失,所以 r 无论取什么值,其所对应的球面的能量都为 E
我们再具体分析某一个点,我们假设半径为1的球面上的某一个点的能量是 I .那么就由 E=4π×r²×I(该点的能量) 公式,推出:

  • 半径为1时,E=4πl
  • 半径为r时,E=4πr²·L(能量,未知)

根据能量守恒定律可以推出 L=l/r²

在这里插入图片描述
这里可以简单说明一下,在上上图说到的光源到球面的半径其实对应到上图就是光源到着色点的距离。

图中的公式:
在这里插入图片描述

  • (I/r²)表示有该着色点有多少能量到达。
  • max(0,n·l)表示到达的能量会有多少被接收。取值范围从0开始是只考虑反射,不考虑折射。前面提到了,单位面积接受到光的能量与 法向量和光线夹角有关,而我们一般认为,如果夹角的绝对值大于90°时没有意义。
  • 其中kd指的是一个系数,代表的是一个物体本身的颜色,或者是材质。因为不同的材质和光线作用的结果不同,所以还要再乘以这个系数。如果:
    • kd=1 表示表面完全不吸收光线,会全部反射出去。
    • kd=0 表示表面是黑的,接收到的光线会被完全吸收,不发生反射。
  • 通过上面的公式也可以知道漫反射跟 观察者角度v 完全没有关系(光线被均匀地反射到各个方向上),即不管从任何角度去看该着色点,明暗效果应该都是一致的。

在这里插入图片描述
上图给出了光源处在左上方,但随着kd从左往右依次增大,球体表面的亮度也发生了改变。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值