games101学习笔记_Shading3(着色)

回顾Shading1和Shading2

  • Blinn-Phong光照模型
  • 着色模型/频率
  • 图形管线
  • 纹理渲染

Shading3主要内容

  • 重心坐标(Barycentric Coordinates)
  • 纹理问题(Texture queries)
  • 纹理应用

插值 - 重心坐标 (Barycentric Coordinates)

为什么要插值?

  • 能够获得三角形三个固定顶点的属性,但是不知道三角形内部的属性
  • 希望三角形内部属性能有一个平滑的过渡效果

重心坐标(Barycentric Coordinates)

重心坐标是定义在一个三角形上的。
首先有一个三角形ABC,重心坐标指的是,在三角形ABC三个点所形成的的平面内任意一点(x,y)都可以表示为三个顶点A,B,C的线性组合。

  • ( x , y ) = αA + βB + γC
  • α + β + γ = 1

需要注意的:

  1. 和为1是为了限制点在三角形所在的平面内。
  2. 如果则该点在三角形内部,则三个系数应该均为非负数。
    在这里插入图片描述

如果我们想要的点在A点上,则:

  • (α , β , γ) = (1 , 0 , 0)
  • (x , y) = αA + βB + γC = A

可以通过面积比来计算某个点的重心坐标
在这里插入图片描述

三角形自身的重心坐标为:
在这里插入图片描述

重心坐标的一般表达式:
在这里插入图片描述

重心坐标的应用

根据重心坐标,我们就可以计算或者推导出三角形内部某个点的一些属性。
如果要做插值,同样应该用重心坐标去将顶点处的属性值线性组合起来。
在这里插入图片描述
Va,Vb,Vc可以是位置、纹理坐标、颜色、向量、深度、材质属性等等。
在这里插入图片描述
注意: 在投影变换下,无法保证重心坐标不变。如果想插值三维属性,应该取三维空间中的坐标,计算重心坐标后插值。而不能在投影之后的三角形里面做。
“深度”:先利用逆变换,找到三维坐标,在三维空间中把深度插值好,再转换过来。

应用到渲染中(Texture Applying)

简单纹理映射:漫反射颜色(Simple Texture Mapping:Diffuse Color)

for each rasterized screen sample (x,y)://usually a pixel’s center (u,v) = evaluate texture coordinate at (x,y);//using barycentric coordinates
  texcolor = texture.sample(u,v);
  set sample’s color to texcolor;//usually the diffuse albedo Kd (这里可以回顾Blinn-Phong光照模型)

纹理放大[Texture Magnification(Ease case)]

一个简单的案例:

  • 一般不想要的结果——纹理分辨率不足
  • 纹理上的一个像素——a texel(纹理元素,纹素)

在三角形的光栅化过程中, 由于纹理的分辨率不够(纹理分辨率越低,同一个纹理坐标对应的uv区间越大), 大量的像素点映射到了同一个像素上。
在这里插入图片描述

双线性插值(Bilinear interpolation)

如果不考虑其他方法,在处理下图中的那个红点的时候,在求这个红点的值会是一个非整数,我们一般会将它当作像素中心来处理,这导致很多点都投影到一个相同的位置,造成图片的精度不高。为了解决这样的问题,我们会采用双线性插值来处理。
在这里插入图片描述

Linear interpolation (1D) 线性插值:
在这里插入图片描述

为了提高纹理采样的效果,可以采用双线性插值。

  1. 取纹理坐标周围的四个像素, u00,u10,u11,u01。该点考虑了周围四个点像素,在四个点围成的区域内有一个平滑的过度。
    在这里插入图片描述

  2. 先在水平方式对u00 u10进行插值得到一个颜色假设为 u0

  3. 然后继续在水平方向对 u01 u11进行插值获得另一个颜色假设为 u1

  4. 最后在竖直方向对 u0、u1进行插值来获得最终的颜色值。
    在这里插入图片描述

  5. 最后在竖直方向上,在原先已经插值出来的两个水平u0、u1上进行插值,算出竖直方向的最后结果。最终结果一致。
    在这里插入图片描述

注意: 以上过程也可以反过来,先竖直再水平操作也可以。

图片效果:
在这里插入图片描述
可以观察到,第二幅图(使用双线性插值来处理)的显示效果比第一幅图要好。

双三次插值(Bicubic Interpolation)

这个方法与双线性插值类似,不同的是双线性插值只取周围四个像素进行处理,但是双三次插值采取周围的十六个像素进行处理,计算量会比Bilinear大,但是效果更好。

纹理放大[Texture Magnification (hard case)]

在这里插入图片描述
出现右边那样的问题(远处出现莫尔纹,近处出现锯齿):

  • 对于屏幕上的某一个像素, 这个像素并不是和纹理上某个坐标一一对应的。
  • 而是每一个像素对应了纹理上的一块区域, 注意, 这个区域其实也不一定是一个矩形,就算是矩形也不一定是与坐标轴两两垂直的。离我们近的时候,其对应的区域小,离我们远的时候,对应的区域大。
  • 当像素覆盖的纹理区域很大的时候, 再将纹理坐标中心对应的像素直接认为是这一个像素的颜色时,是有问题的。

解决上面那个问题可以使用超采样,对每个像素点应用N倍采样点进行采样(比如512),最后进行平均,可以得到比较好的效果,缺点是计算量比较大。

点查询问题和范围查询问题:
在这里插入图片描述

  • 点查询问题(Point Query)
    给定一个点,然后得其值。(通过双线性插值或者双三次插值等方法)
  • 范围查询问题(Range Query)
    不做采样,给定一个区域,立刻得到其覆盖范围的平均值。
    也有其他种类的范围查询,需要得知范围内的最大值or最小值等。
    范围查询应该支持查询任意大小的范围。

MipMap

允许:

  • 快(fast)
  • 大概地(approx.)
  • 平方的(square)

的正方形的范围查询(range queries)
在这里插入图片描述
MipMap能够生成一系列的纹理。上面这张图从一开始的原图(128128)开始,每一张图的分辨率都缩小一倍。所以对于一个NN的纹理, 最多有log2(N)层。
生成纹理图层如下:
在这里插入图片描述
所以随之而来的问题:相比于原始的图片,引入了多少额外存储量?
所有的纹理加一起消耗的存储量为原来的纹理存储量的4/3,这是一个级数求和的问题。也就是多消耗了1/3的存储量。与原图相比多引入了三分之一的存储量。

在这里插入图片描述
将屏幕空间坐标(x,y)映射到纹理空间坐标(u,v)。就拿上方左图中的红点来说,在屏幕坐标中确定好了一个红点,然后确定它的邻居。在将其映射到纹理空间坐标上,这样就能得到他们一一对应的前提。
在这里插入图片描述
我们要求的问题是: 左图左下角的红点像素在纹理空间中要占据多少范围(即右图中的红色不规则四边形区域)。

因为MipMap只能在正方形范围内进行查询,所以我就只要求在纹理空间中左下角的像素到上下两个像素点距离的最大值,然后将这个最大值作为正方形范围的边长。
在这里插入图片描述

因为在像素空间中,两个像素之间的距离就是一个像素正方形的边长大小,所以在纹理空间中也是求相应像素的距离作为原像素点在纹理空间中所占范围的大小。

边长L的求法:
在这里插入图片描述
当我们想要查询某个边长为L的区域在某层mipmap中会变成一个像素的大小,根据这个像素就能知道他的平均值。
在这里插入图片描述

MipMap的实现效果

在这里插入图片描述
图中可以看到,有些地方为渐变,但有的地方就是突变,并不连续,为什么?比如说在近处的可能在第一层查,稍远处就在第二层了,更远一些就在第三层查,没有1.5层,1.8层的,所有就会导致变化不连续。如果我希望能查1.8层该怎么办?用插值。

三维插值:
在这里插入图片描述

  • 先找第一层,再找第二层,然后在两层内部分别进行双线性插值,在两层上的查询先做出来。
  • 然后再将这两个双线性插值的值合在一块,就能在这个层与层之间再做一次插值(这个插值不是水平的也不是竖直的,而是层与层之间的),也就是说做了三步插值。

因为在层中进行插值使用的是双线性插值,在层间又进行了一次线性插值,所以这种方法是三线性插值。

三线性插值得到的结果:
在这里插入图片描述

MipMap的限制

点采样:
在这里插入图片描述

超采样:在这里插入图片描述
MipMap效果图:
我们会发现使用MipMap方式,远处的图会糊掉。
在这里插入图片描述
也就是Overblur——过度模糊,那么为什么呢?

在前面已经提过,MipMap只能查询一个方块(正方形)的区域内(范围)。但如果不是方形区域呢?后面的三线性插值都是一个近似的估计,近似的太多,远处就会出现这样一种过度模糊的效果。

但这只是近似的,因为使用插值的方法毕竟不是自己算出来的。

各向异性过滤(Anisotropic Filtering)

在这里插入图片描述
效果比三线性插值好

  • 在mipmap的基础上,针对不同的长宽比也进行了一系列的计算。
  • 开销是原来的三倍,但MipMap开销只比原来多了1/3.
  • 生成的是 RipMap

在这里插入图片描述
可以看到上图中,在水平方向上,高度没有变,但是宽度被不断的压缩,而在竖直方向,宽度没有变,高度被不断的压缩。也就是说,各向异性过滤比MipMap多做了这些工作,能够为宽高不均匀的图片进行压缩。

他处理也不再局限于正方形,而是扩大到了矩形。

在这里插入图片描述
从上图中可以看出,屏幕上的像素映射到纹理空间上时,并不总是一个规则的形状,可能会出现这种斜的长方形或者别的形状,那这种情况下以上两种方法就都不能很好地解决。

EWA过滤(EWA filtering)

对于这种情况,采用另一种方法:
EWA filtering
在这里插入图片描述
用很多圆形去覆盖不规则的形状
多次查询,找到可以覆盖的圆形,性能消耗略大。

纹理应用

现代GPU,可以将纹理理解为一块内存以及可以对该区域做滤波(范围查询)
In modern GPUS, texture = memory + range qurey(filtering)

Environment Map

在这里插入图片描述
环境光贴图——均假设环境光来自无限远处,没有深度意义。

Environmental Lighting

在这里插入图片描述

Spherical Environment Map——材质球(同U3d理解)

在这里插入图片描述

Spherical Map——Problem

当把整个球体展开为一张图时,会发现图片产生了扭曲。(也就是球面的贴图展开)
在这里插入图片描述

球面贴图扭曲的解决方法——Cube Map

将球体用一个正方体包围盒进行包围,然后假设球面对应的信息会映射到包围盒上,也就是cube Map。
在这里插入图片描述

展开效果图:
在这里插入图片描述

凹凸贴图(Bump Map)

在这里插入图片描述

除了在纹理中直接存储光照信息以外,还能在纹理中存储一些顶点的法线或者高度信息, 从而对顶点的法线方向进行扰动, 在没有改变模型的几何形状的前提下, 在模型中产生凹凸的质感
在这里插入图片描述
这是因为人们看到的明暗变化,其实就是法线变化从而影响着色。而明暗存在对比,那么人们的视觉就会认为存在凹凸效果。

增加了表面的信息但却没有增加更多的三角形:

  • 扰乱了每一个像素的表面法线(只针对着色的计算过程)
  • 通过定义不同位置的高度,通过邻近的这个位置的高度差来重新地计算它的法线。

纹理定义的是任意一个点它的相对高度的移动,通过高度的变化就可以改变这个法线。

在这里插入图片描述
比如说上图的p点,本来它的法线方向应该是垂直于球面向上的,但是有了高度差之后,就在他对应的高度上做法线,是垂直于波形向上的。通过这里可以看出是如何通过高度差来改变法线的。

如何扰乱法线(在平面上)

计算方法:
在这里插入图片描述

  • 蓝色波浪线是由凹凸贴图定义出来的。
  • 原始表面法线 n( p ) = (0 , 1)
  • dp是那个点的导数(切线方向),也称为梯度,在凹凸贴图的那个点上,向右移动一个单位的距离,计算出dp。
  • 所以dp的高度差是 dp = c * [ h( p+1 ) - h( p ) ] —— c是一个常数,用来定义凹凸贴图的点到底大不大。
  • 会发现凹凸贴图的切线向量就是( 1 , dp )。
  • 改变法线。会发现凹凸贴图上的法线就是 法线 凹凸贴图的 切线 的垂直。
  • 所以将切线 逆时针旋转90° ,可以得到法线。n( p ) = (-dp , 1).normalized()。(归一化是因为法线必须是单位向量)

如何扰乱法线(在3D上)

  • 原始表面法线 n( p ) = (0 , 0 , 1)
  • dp的u的高度差是 dp/du = c1 * [ h( u+1 ) - h( u ) ] (在UV图上)
  • dp的v的高度差是 dp/dv = c2 * [ h( v+1 ) - h( v ) ] (在UV图上)
  • 所以将切线算出来后,再 逆时针旋转90° ,可以得到法线。n = (-dp/du , -dp/dv , 1).normalized()

注意: 我们定义的是局部的坐标系,我们在这个坐标系里面认为法线永远是(0 , 0 , 1),并且他有两个垂直的分量。形成一个局部的坐标系,在这个坐标系中通过纹理映射的方法,将法线改变了一点,然后我们再将这个算出来的法线再重新计算回世界坐标里。

位移贴图(Displacement mapping)

在这里插入图片描述

  • 凹凸贴图与位移贴图其实基本思想是一样的,都是改变法线。不同的是凹凸贴图是通过原始的对应的凹凸贴图换算法线,不改变三角形本身。但位移贴图是真的会改变三角形的顶点信息。
  • 所以再看上图的时候会发现凹凸贴图在球体边缘的时候会露馅,没有凹凸不平的感觉,并且在中间也没有投影到自身的阴影。而位移贴图就有,可以看出位移贴图的效果比凹凸贴图的要好。
  • 这也意味着位移贴图几何模型需要更加精细,电脑的工作量在位移贴图上更大。

三维纹理

定义在三维空间中的纹理。

下面的图是只是定义了一个噪声函数(柏林噪声),可以通过噪声函数在三维空间中查询这个三维纹理的一些数值,并没有实际地将图存储到内存里。
在这里插入图片描述

记录信息

通常会记录位置中的一些其它信息。
下图是表示 算出模型的简单着色后 再乘以 计算好的环境光遮蔽纹理就可以得到 第三个图的结果。
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值