重心坐标(为了做插值)
1.为什么要插值
我们要做的很多操作是在三角形顶点上完成、计算的,希望在三角形内有一个平滑的过度Texture coordinates, colors, normal vectors, …
2.什么是重心坐标
三角形所在平面任意点(x,y)都可用三顶点(α β γ)的线性组合表示,如果三个都是正的就是在三角形内,否则就是在三角形外
顶点的重心坐标
3.重心坐标求解公式
4.注意事项
重心坐标不能保证投影后不变
所以三维的要在三维中找到重心坐标再做插值,而不能投影后做插值,如果是投影后的坐标可以通过变换矩阵的逆矩阵得到变换前的3维坐标
应用纹理
1.简单纹理映射
一个点/像素 →(通过重心坐标插值)uv → 查询找到对应texcolor代替kd,但是纹理过大或者纹理过小都会出现问题
2.纹理太小的情况
双线性插值
- 找相邻的4个点
- 做上下双线性插值(水平两次,竖直一次)
双向三次插值Bicubic Interpolation
相邻的16个点做水平和竖直的差值
3.纹理太大的情况
如果简单uv映射的话会出现摩尔纹,原因是远处一个像素或者采样点覆盖的纹理区域很大,不能通过简单采样就覆盖那么大区域
解决方法1:超采样-MSAA
代价太大
解决方法2:不采样:Mipmap
- 是一种算法问题:范围查询
- mipmap允许做范围查询:快;不准;只能做近似正方形的查询
- Mipmap
- 从一张图生成一系列图
- 每一层分辨率变为原来的一半
- 有多少层?每次变为原来的1/2,所以有Log2n层,n是原始层分辨率
- 存储量为4/3(比原来多1/3)
mipmap如何查询层LOD
根据相邻像素对应到纹理上的距离,然后根据距离L可以得到层级D,也就是在这一层纹理的大小正好会对应到一个像素的大小
如果要查1.8这样的层怎么办?(连续的)→三线性插值Trilinear Interpolation
比如1.8层就是分别在第一层和第二做两次双线性插值,然后再将这两层的结果进行插值,比如这里就是0.8*2层+0.2**1层
Mipmap的局限性:Overblur过度模糊
解决方法
(a)各向异性过滤Anisotropic Filtering
- “几X”是指几层,例如2X对应的就是下图的前2*2区域,只和显存有关系
- 查询近似矩形区域
- 开销是原本的3倍
- 仍然不能解决倾斜的矩形的区域的问题
(b)EWA过滤
可以解决对应不规则形状区域的问题,对于任意不规则形状,都可以拆解成多个椭圆形,缺点就是需要多次查询,还不太懂这个
4.环境贴图
可以看到球型环境贴图会有扭曲问题
扭曲问题解决:Cube map,将六个方向的环境光照信息存储在六个方向的六个贴图上
5.凹凸贴图和位移贴图
凹凸贴图
- 只改变纹路,不增加三角形
- 每个pixel做一个“扰动”
- 通过定义不同高度邻近位置的高度差,来重新计算法线。
- 可以看到下图原来的法线经过法线贴图扰动后变成了斜向上的
如何计算扰动后的发现?
原始的平面发现都是垂直向上的,应用凹凸贴图以后变成了弯曲的且有了相对的高度差,计算法线的方法是先计算切线,直接用后一个点的高度减去当前点的高度,这个貌似是斜率,常数c可以理解成凹凸的强度。然后得到的切线就是(-dp,1),逆时针旋转90度以后得到法线
在3d的情况下:
原本法线(0,0,1)——》求出梯度(导数/微分) u,v———》切线——》法线,可以类比一维的推导方法,中间推导过程较为复杂
位移贴图
- 和凹凸贴图用一样的纹理
- 真的移动了顶点的位置
- 三角形顶点要足够多
→ DirectX 中的动态曲面细分:开始先用粗糙的三角形,应用Texture的过程中检测是否需要把三角形拆分的更细
6.三维纹理
定义了一个噪声函数 → 空间内任意的一个点都有一个解析式来算出噪声的多少 → 一系列处理 → 变成我们需要的样子
7.Texture可以记录一些已经算好的信息
例如:阴影可以计算好,直接写在Texture里,也就是AO贴图
8.3D Texture 和体积渲染
核磁共振成像或者成像扫描人体的某个部位可以返回三维空间的信息,比如密度,可以用来进行体渲染