GAMES101-09:着色3:纹理的应用
九、着色3:纹理的应用
9.1 重心坐标 Barycentric Coordinates
为什么需要插值
- 我们的很多操作是定义在顶点上的
- 我们需要在三角形内获得平滑的值
插值什么内容
- 纹理坐标、颜色、法线
怎么做插值
- 重心坐标
9.1.1 重心坐标是什么
定义在三角形上:三角形所在平面的任意一个点的坐标,都可以用三个顶点坐标的线性组合表示,且\(\alpha+\beta+\gamma=1\)
- \((x,y)=\alpha A+ \beta B + \gamma C\),可以得到一个坐标\((\alpha,\beta,\gamma)\)
- 如果在三角形内,则\(\alpha,\beta,\gamma\)均为非负的
求\(\alpha,\beta,\gamma\):通过面积计算
三角形的重心:分成的三个三角形面积相等
使用公式计算:
9.1.2 重心坐标插值
注意:投影后,重心坐标可能会改变,因此插值三维属性,应该使用三维坐标
9.2 纹理的基础应用
9.2.1 简单纹理映射:漫反射颜色
对每一个屏幕中的采样点\((x,y)\):
- 通过重心坐标插值,计算\((x,y)\)对应的纹理坐标\((u,v)\)
- 得到纹理中,\((u,v)\)所在点的颜色,记为
texcolor = texture.sample(u,v)
- 将该采样点的颜色,设置为
texcolor
9.2.2 纹理放大:双线性插值 Bilinear interpolation
像素pixel <=> 纹理元素texel,纹理需要放大时,多个pixel会对应到同一个texel上
纹理过小:失真
- 找到临近的四个点
- 计算水平距离
s
和垂直距离t
,均为[0,1]
之间的值 - 定义线性插值操作:\(lerp(x,v_0,v_1)=v_0+x(v_1-v_0)\),\(x\)为
[0,1]
之间的值 - 进行两次线性插值操作:
- 水平方向:\(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)\)
9.2.3 纹理缩小
纹理过大:远处摩尔纹,近处锯齿
- 远处,一个像素覆盖了纹理上的很大一块区域,因此会存在走样
9.2.3.1 Mipmap
Mipmap:允许做快速、近似、正方形的范围查询
每一层均将上一层缩小到原来的一半
- 预处理纹理
- 多了1/3的存储量
计算某个像素对应到纹理的正方形区域
- 将屏幕上的某个像素点
p1
及其两个邻居p2,p3
对应到纹理上的三个点t1,t2,t3
- 在屏幕上,
p1
与p2
的距离为1
,p1
与p3
的距离为1
- 在纹理中,
t1
与t2
的距离为L1
,t1
与t2
的距离为L2
- 取
L=max(L1,L2)
,则该像素在纹理空间上对应的正方形区域为,以t1
为中心的L×L
的区域
- 将屏幕上的某个像素点
计算正方形区域的平均值
- 假设正方形为
1×1
,则可以直接在0
层中获得该区域的平均值 - 假设正方形为
4×4
,则可以直接在1
层中获得该区域的平均值 - 因此,我们可以在第\(D=log_2L\)层中获取该区域的平均值
- 如果\(log_2L\)不是整数,则可以通过线性插值,获得该区域的平均值
- 每一层的查询,使用了一次双线性插值,最后又进行了一次线性插值,因此称为三线性插值
- 假设正方形为
缺点:在远处会完全模糊overblur
9.2.3.2 各向异性过滤
Anisotropic Filtering:各向异性过滤,对矩形的区域快速查询平均值
- 各向异性过滤:水平、竖直压扁,开销为原本的3倍
- EWA过滤:将图像分为一个个的椭圆
9.3 纹理的其他应用
现代GPU中,纹理的本质:是一块内存区域,且可以进行范围查询
9.3.1 环境贴图 Environment Map
- 环境贴图:即为空间中的某个点,向上下左右前后六个方向,所能接收到的光
- 可以通过环境贴图,进行光照计算,进而实现环境光渲染
- 基本假设:环境光来自无限远处,只记录环境光的方向信息
- 可以使用Spherical Map或者Cube Map表示
由于立方体的各个面都是均匀的,因此能很好的避免天空球的极点消失现象
- 天空盒只记录方向信息
- 需要先判断某个方向是属于哪一个面上的
9.3.2 凹凸贴图 & 法线贴图
- 凹凸贴图:定义某个点的相对高度(沿法线移动的距离),从而改变周围像素的法线方向
- 法线贴图:定义某个点的法线
计算修改后的法线
一维贴图,修改像素的法线:flatland
- 设原来的表面法线
n(p)=(0, 1)
- 计算梯度:
dp=c*[h(p+1)-h(p)]
- 则切线为:
(1,dp)
- 因此更改后的法线为:
n(p)=(-dp, 1).normalized()
- 设原来的表面法线
二维贴图,修改像素的法线:局部坐标系下
- 设原来的表面法线
n(p)=(0, 0, 1)
- 计算梯度:
dp/du=c1*[h(u+1)-h(u)]
,dp/dv=c2*[h(v+1)-h(v)]
- 因此更改后的法线为:
n(p)=(-dp/du, -dp/dv ,1).normalized()
- 设原来的表面法线
9.3.3 位移贴图 Displacement Mapping
- 与凹凸贴图类似,但是会直接更改三角形顶点的位置
- 要求原有模型的三角形比较细,要求模型的三角形顶点之间的间隔,比纹理之间的间隔小
9.3.4 三维纹理
- 定义一个三维空间的噪声函数,可以得到三维空间中,任意一个点的属性
9.3.5 保存预处理的数据
9.3.6 三维纹理 & 体积渲染
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 华风夏韵!
评论