6.Shading(纹理映射、其他应用))

发布时间 2023-07-01 13:13:45作者: oOLzYOo

纹理映射

  • 在物体的不同位置定义不同的属性,用来定义点的不同属性(例如漫反射系数)

  • 把地球仪表面的“皮”,剪开平铺就是一个平面。
  • 所以说任意三维物体的表面摊开就是二维平面。

纹理映射座标

  • 在美术人员建模时,通常会在建模软件中利用纹理展开技术把纹理映射座标(texture-mapping coordinates)存储在每个顶点上。
  • 纹理映射座标定义了该顶点在纹理中对应的2D座标,通常用(u,v)表示,u表示横向座标,v表示纵向,俗称UV座标。
  • 纹理大小可以是多种多样的,可以使256x256或者1024x1024,但是顶点UV座标范围通常被归一化到\([0,1]\)

问题

已知三角形三个顶点的UV坐标,怎么获得三角形内部的某个像素点的UV坐标呢?

──插值

重心座标

为了在三角形内部对各个属性做插值,我们引入了重心坐标。

  • 为什么要引入插值?

可以指定三角形内部任意顶点的值

在三角形上获得平滑的变化值

  • 什么属性可以用以插值获得?

纹理、颜色、向量等属性

  • 怎么做插值?

引入重心坐标

  • 三角形所在的平面内的任意一个点(x,y)可以用αA+βB+γC来表示,A,B,C都为某个点。
  • (α,β,γ)用来表示三角形的重心坐标,当满足α+β+γ=1时表示该点(x,y)在三角形所在的平面内。
  • 当 α,β,γ都>=0,时,该点一定在三角形内部。

  • A点自己的重心坐标为(1,0,0)

  • 重心点与三个顶点相连后获得三个三角形,Aa表示顶点A对面的(不相邻A点)的三角形。
  • α=A顶点对面三角形Aa的面积/(三个三角形的面积)

特殊点:三角形重心

  • (x,y)的重心坐标为(1/3,1/3,1/3),因为三个三角形的面积相等。

任何一个点的重心坐标通用公式

\[\alpha=\frac{-(x-x_B)(y_C-y_B)+(y-y_B)(x_C-x_B)}{-(x_A-x_B))(y_C-y_B)+(y_A-y_B)(x_C-x_B)}\\\beta=\frac{-(x-x_C)(y_A-y_C)+(y-y_C)(x_A-x_C)}{-(x_B-x_C))(y_A-y_C)+(y_B-y_C)(x_A-x_C)}\\\gamma=1-\alpha-\beta \]

利用重心座标插值

  • VA,VB,VC可以为各种属性,例如坐标,材质、颜色,深度等。
  • 但是,在投影变换下,重心坐标不能保持不变。
  • 所以如果要插值三维空间中的属性,我们应该取三维空间中的坐标(ABC),重心坐标V也是三维中的坐标,做完插值后再做投影变换。

把纹理应用到渲染中

  • 对于每一个栅格化屏幕样本(通常是像素的中心点)
  • 三角形任意点的纹理坐标(u,v)可以通过插值获得
  • 获得纹理颜色=texture.sample(u,v)
  • 就可以认为该纹理颜色为漫反射的系数Kd

纹理放大

  • 上图展示的是低分辨率的纹理,放大后的效果,三图对应了三种不同的处理方法
  • 对于平面上的任意一个点,我们可以获得其纹理上的对应位置,该位置不一定是整数,需要四舍五入,在一定范围内查找一个相同的纹理上的像素,叫做 texel,得到了第一图Nearest,因为一定范围内的像素都是同一个texel。
  • 图二为双线性插值后的结果。
  • Bicubic,取了16块像素,做插值计算,更高的计算量。

双线性插值

红点表示实际的屏幕像素位置,黑点表示缩放后的图像像素位置,我们发现实际像素位置与图像像素并不匹配,所以我们需要插值计算实际屏幕像素的颜色。

  • 红点表示在纹理中映射的某一个点的位置
  • 我们取离红点最近的4个像素
  • 取红点距离左下角顶点\(u_{00}\),宽和高分别是s和t(大小0~1之间)
  • 定义操作“线性插值\(lerp(x,v_0,v_1)=v_0+x(v_1-v_0)\),x=0时,结果=v0,x=1时结果=v1,说明该线性插值是像一个滑动块,在v0和v1之间滑动,x=0.5时,结果=0.5v0+0.5v1

  • 通过线性插值操作,对u1和u0的长度做线性插值操作,(水平方向)

    \[u_0=lerp(s,u_{00},u_{10})\\ u_1=lerp(s,u_{01},u_{11}) \]

  • 同理竖直方向,高度做线性插值操作(竖直方向)

\[f(x,y)=lerp(t,u_0,u_1) \]


纹理缩小

  • 纹理要是过大会引起更大的问题

  • 如果我们按之前的做法,纹理坐标插值出任意一个点的坐标,把值写回像素。会得到图二。
  • 远处有摩尔纹,近处有锯齿。

产生这种现象的原因:

  • 近处的像素覆盖的纹理区域较少,而远处的一个像素覆盖了一大块的纹理。
  • 不能通过插值某一个点来表示整块纹理的颜色。

怎么解决:

1.超采样,可行,但是资源消耗过多。

  • 质量高,但成本高
  • 高度缩小时,像素足迹中有许多纹素
  • 像素中的信号频率太大
  • 需要更高的采样频率

2.引入Mipmap

Mipmap

  • 范围查询很快,但是不是很准
  • 仅仅是近似的方形的范围查询
  • 原图层级level0=128128大小
  • level1为 纹理长宽都除以2,level1=6464,依次类推各个层级
  • 我们从原图一直生成了一系列的图,而生成的图通过等比数列计算:

\[S_n=a_1\cdot\frac{1-q^n}{1-q}=\frac{a_1-a_n\cdot q}{1-q}(q\neq1) \]

我们通过mipmap获得了一系列图的大小仅为原图的1/3

怎么做范围查询

  • 图一为 屏幕像素坐标,蓝色点有一些邻居,红色点也有邻居。
  • 图二为 纹理的坐标图
  • 把图里中的像素点和其邻居,映射到纹理中去,得到图二。

\[D=log_2L\\L=max(\sqrt{(\frac{d_u}{d_x})^2+(\frac{d_v}{d-x})^2},\sqrt{(\frac{d_u}{d_y})^2+(\frac{d_v}{d_y})^2}) \]

  • L取的是所测像素映射的纹理空间中的 相邻4个点中距离最大的那个值
  • 在纹理空间中以L为边长的正方形被看做 屏幕像素坐标中1单位像素缩放后的结果
  • 根据D=logx(L)去查询 mipmap的值。D表示mipmap的层级
  • 简化流程:根据模型跟摄像机的距离,计算出不同层级的mipmap来告诉屏幕该怎么渲染
  • 上图是我们使用mipmap的实际渲染效果
  • 发现渲染有颜色上的断层,渐变的效果不连续
  • 这是因为我们设置的mipmap层级都是整数的层级,在不同距离下会使用相同的整数层级mipmap

怎么查询mipmap1.8层的具体数据?

  • 三次线性插值:两次查询,一次修正
  • 再做一次线性插值!

  • 要查询1.8层,我们可以获得第1层的数据,获得第2层的数据,分别对这两层做线性插值
  • 然后对这两层的数据再做一次线性插值。

  • 三次线性插值后的效果

mipmap的局限性

  • 之前的图使用mipmap处理后,远处出现了模糊
  • mipmap只能查询正方形方块

各向异性过滤

  • mipmap相当于等比缩放,在上图中是对角线部分的图
  • 各向异性过滤把不同长宽比的图像都存储下来,在不同缩放尺寸的快速查询效果会比mipmap更好
  • 对于矩形的查询更优化,对于长和宽单独按比例缩放生成各层纹理图。
  • 存储空间是原图的3倍,GPU,显存的压力增加了一些,计算量增加不多。

EWA过滤

  • 任意不规则形状,拆成圆形,再查询。
  • 查询计算量较大。

纹理的其他应用

凹凸贴图

例子:本来如果是想表现一个平滑的球体,2、3百个三角形就能拼出来,但是如果要表现一个凹凸不平的三角形,如上右图,如果使用模型拼出,就需要几何倍数的三角形了,这时候使用凹凸贴图就能很好解决这个问题。

  • 通过人为的制造假的法线,通过纹理映射,获得了假的着色结果,可以让人觉得有凹凸的结果。
  • (如上左图)凹凸贴图(法线贴图)两者意思一致。

凹凸贴图怎么实现?

  • 下图中黑线表示原纹理贴图,黄线表示凹凸贴图
  • p点表示原贴图的法线方向,n表示凹凸贴图的法线方向。
  • 人为地改变了法线的方向,导致人眼看到要凹凸的感觉。

怎么求凹凸贴图的法线方向?

  • 蓝色线为法线贴图表面
  • 原始表面法线n(p)=(0,1)
  • 对法线贴图点P处求导\(d_p=c*[h(p+1)-h(p)]\)
  • 法线与切线相互垂直,可得法线\(n(p)=(-dp,1).normalized()\)

导数定义

位移贴图

  • 凹凸贴图是逻辑上的高度改变,而位移贴图则是物理上的高度改变(改变了顶点的位置),二者的区别就在此处,可以通过物体阴影的边缘发现这点。
  • 要求模型的三角形足够细,三角形顶点的间隔能更得上纹理的高度变化(类似采样频率)

阴影贴图Shadow Mapping

拓展学习:转载自https://blog.csdn.net/xiaoge132/article/details/51458489

性质

  • 如果一个点不在阴影里则,这个点必须同时满足被摄像机和光源观察。
  • 这里主要研究的是点光源

点光源下的阴影

  • 假如在点光源摆设一个摄像机,对场景做投影变换,即可获得一副图
  • shadow mapping保存了点光源处对于物体的深度图
  • 然后从摄像机视角投影出一幅深度图
  • 对比点光源处的深度图和摄像机处的深度图
  • 若两者的深度一致则是光照位置,若不一致则是阴影

注意:

  • 光源投影出的阴影图分辨率会影响阴影的效果,类似采样频率过低(游戏中的阴影质量选项)
  • 理论上只能适合于 硬阴影

三维噪音贴图+实体建模

  • 定义一个三维空间中的噪声函数,来表现裂痕。

提供预先计算的阴影

  • 左图为普通的shading着色。
  • 中图为计算好的环境光遮蔽的纹理。
  • 右图为左图乘以中图的结果。