Games101-Cp3-Shading

发布时间 2023-06-18 17:15:53作者: xkyl

Shading的过程就是对物体应用材质的过程。Shading\(\not=\)Shadow。着色模型不包括阴影。

Z-Buffering

深度缓存用于做深度测试时对深度进行比较。在\([0, 1]\)之间取值。应该是可视范围与深度的相除?
在开启深度测试的时候,与深度缓存进行比较。如果小于对应像素的深度值则绘制。

Blinn-Phong反射模型

该简单着色模型由三部分光构成:1.漫反射diffuse2.高光specular3.环境光ambient。对应的输入为:1.观测方向\(\vec{v}\) 2.法线方向\(\vec{n}\) 3.光照方向\(\vec{I}\) 4.表面材质参数。注意上述三个方向均是从像素点往外出射。因为Shading是局部的,同时我们在对应的着色器也是逐顶点/逐片元的局部操作。

Diffuse 漫反射

\[L_d = k_d(I/r^2)max(0,\vec{n}\cdot\vec{I}) \]

这是Lambertian计算漫反射的公式。首先\(k_d\)是漫反射系数,实际上就是该点的颜色,即光线被着色点反射的部分,可以直接再uv纹理上取值。第二个部分则是光在能量传播中的损耗,我们假设漫反射的光在传播过程中是均匀发散的,能量是以球壳的方式传播,并假设在半径为1的球上光的强度为\(I\),则在距离为\(r\)的球壳上与\(r^2\)成反比,因为球的表面积公式。第三部分是能量接收部分,与光线方向和法线的夹角有关。

总结,漫反射与传播距离和光线方向有关,与观察方向无关。

Specular 高光

\[L_s = k_s(I/r^2)max(0,\vec{n}\cdot\vec{h})^p \\ \vec{h} = bisetor(\vec{v},\vec{I}) \]

高光的强度与视线方向\(\vec{v}\)有关,即视线和反射光的夹角越小,对应强度越大。但并不好计算,于是引入半程向量做近似处理。将反射光向量与视线向量的夹角\(\iff\)相当于法线\(\vec{n}\)与半程向量\(\vec{h}\)之间的夹角大小。一般\(_p\)取100~200以降低高光范围,越高高光越集中。

Ambient 环境光

\[L_a = k_aI_a \]

与任何方向无关,为一常数。


Blinn-Phong计算公式如下 $$ L=L_a+L_d+L_s $$

着色频率

判断着色应用在什么位置。

  • Flat Shading 由一个顶点颜色作为整个三角形的颜色。
  • Gouraud Shading 逐顶点着色 在顶点着色器完成,在光栅化阶段插值得到各片段的光照信息。但高光结果不行,因为高光不是线性变化的。
  • Phong Shading 逐片段着色,根据输入的顶点法线信息在光栅化阶段进行法线插值,然后在片段着色器中计算光照信息。

法线

  • 逐顶点法线,需要满足以下两个条件1.最好要求是基础的几何体。2.对周围的平面法线进行平均。

\[N_v=\dfrac{\sum_i N_i}{||\sum_i N_i||} \]

  • 逐像素法线,通过重心坐标确定。
    为了得到三角形内部对应所需变量,并且能在三角形内平滑过渡。采用三角形重心坐标。用于计算纹理坐标、颜色、法线等。

\[(x, y)=\alpha A+\beta B+\gamma C \\ \alpha+\beta+\gamma=1 \\ \alpha = \dfrac{S_a}{S}, \beta = \dfrac{S_b}{S}, \gamma = \dfrac{S_c}{S} \]

重心坐标不能应用在投影后的坐标,而是只能用在世界坐标系下。

渲染管线

直接看我写的另一个blog。我认为是比较清楚。
https://www.cnblogs.com/xkyl/p/17473565.html

纹理 Texture

uv纹理坐标在\([0, 1]\)之间。三角形顶点对应着纹理坐标,在光栅化的同时纹理坐标也一起被光栅化。纹理在应用的过程中会出现两种常见情况:

1.纹理过小

当纹理分辨率不足时,对纹理坐标的取值非整数(ps:注意这里的整数是未归一化的纹理坐标。而不是uv坐标)。

  • Nearest 采样最近像素,这是对纹理坐标直接取整,会出现明显锯齿。
  • Bilinear 双线性插值,对应锯齿较少,对考虑非整数纹理坐标周围四个像素的像素值。具体步骤如下1.取非整数点相邻的四个整数坐标的纹素 2.在两条平行线上做一维线性插值 3.计算对应像素值。

\[lerp = v_0 + x(v_1 - v_0) \\ 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) \]

  • Bicubic 双三次插值

2.纹理过大

假设一个平面直接通过纹理坐标对纹理进行采样,近处会出现锯齿走样,远处会出现摩尔纹。近处可以通过上面介绍的线性插值来减少锯齿。而远处是因为覆盖的纹理范围大,采样的信号频率低。一般有两个方法解决 1.超采样SS 2.Mipmap。因为超采样的消耗比较大,不是我们的第一选择。下面介绍Mipmap的过程。

Mipmap

是一种范围搜索的方式。

  • 生成Mipmap图。我们先对原始图进行处理,生成原来一半边长的缩略图,并且多次生成多层的Mipmap。多生成部分的缩略图只多占原来的内存的1/3.(将多生成的Mipmap乘三,对应的内存极限接近于原始图大小)

  • 计算取第\(D\)层的Mipmap纹理。取该像素在原始图上的uv坐标相邻上方和右侧的像素。

\[L = max(\sqrt{(\dfrac{du}{dx})^2 + (\dfrac{dv}{dx})^2}, \sqrt{(\dfrac{du}{dy})^2 + (\dfrac{dv}{dy})^2}) \\ D = \log_2{L} \]

  • 三线性插值。希望在层与层之间能有平滑变化的纹理。对\(D\)层做双线性,\(D+1\)层做双线性,对应结果做线性。

Mipmap局限性。因为三线性插值可能会导致远处过分模糊。有两种解决方法,

  • 1.各向异性过滤,对于一些特殊覆盖范围的纹理采样(如长条等)。我们分别对u轴、v轴进行压缩得到Ripmap,解决特殊纹理模糊情况,对应内存会增加三倍。
  • 2.EWA filtering 不规则图形覆盖面积。

对应还有各种各样的贴图。环境贴图,CubeMap,凹凸,法线贴图。后面虎书再具体展开讲。

对应作业三是模型显示以及上不同贴图,没太搞懂IBN矩阵的内容。先放过。

感谢你看到这里,Cheers!