纹理是什么?
一种可供着色器读写的结构化存储形式,存储信息不仅仅局限于颜色信息,高度、纹理通道、法线等各种信息
一维纹理由二维数组构成;二维纹理则由四维数组构成
为什么使用纹理?
纹理可以代替一些几何细节
牺牲了几何细节 = 建模工作量大量减少,存储空间减少,读取速度减少
纹理管线:
模型空间位置=>投影函数(展UV阶段使用,并存储于顶点数据中)
=>纹理映射=>纹理坐标(texture)=>通讯函数=>新纹理坐标(归一处理)
=>纹理采样(避免依赖纹理读取,避免让片元着色器计算纹理,尽可能让纹理计算位于顶点着色器中)=>纹理值
纹理采样设置:
Wrap Mode(包装模式):
决定UV值在[0,1]以外的表现
OpenGL--“包装模式”(Wrapping Model)
DirectX--“纹理寻址模式”(Texture Addressing Mode)
Filter Mode(滤波模式):
放大Magnification
最邻近(Point):当图像放大时,每一个像素会读取它最邻近的一个像素点,多个像素对读取同一个纹理,因此会呈现出块状,但是节省消耗
双线性插值(Billinear):对每个像素点都找到相邻的四个像素点,进行二维的线性插值来得到像素的混合值
立方卷积插值(双三次插值)(Trilinear):
卷积公式:
光滑曲线插值:
效果对比:
Mipmap(三线性插值):
Mipmap纹理图:
Mipmap纹理图多占用1/3内存
如何选择正确的level:(代码如下)
float dx = ddx(i.uv);
float dy = ddy(i.uv);
float lod = 0.5 * log2(max(dot(dx, dx)));
float3 albedo = tex2Dlod(_MainTex, float4 (1.uv, 0, lod)).rgb;
得到的值一般不是整数,在两级层分别进行线性插值后,两层之间再进行线性插值,即三线性插值
各向异性过滤Anisotropic Filtering:
CPU渲染优化常见方式—纹理图集/数组
命令缓存区CPU添加和GPU读取的过程是相互独立的,GPU的渲染速度远远快于CPU发送命令的速度,DrawCall数量太多的情况下,CPU就会花费大量的时间在提交DrawCall上,
而降低这些DrawCall常见的方法是纹理图集跟纹理数组,以及无约束纹理,
均是为了避免纹理渲染的时候频繁改变纹理所带来的消耗,
实际应用中做最常见的是纹理图集,纹理不一定要是正方形的,纹理形状不受限制
GPU渲染优化常见方式——纹理压缩
(如果游戏速度受限于显存带宽,往往都是所使用的纹理太大了,GPU没有办法快速的处理)
减少了资源在CPU中进行解压的过程
减小了包体大小,减小了数据量级,减轻了贷款计算的压力
内存使用率更高
立方体贴图CubeMap:
使用三维纹理坐标对立方体映射进行采样
使用六幅二维的纹理图像,构成了一个以原点为中心的立方体
凹凸贴图Bump Mapping:
在不增加顶点的情况下,通过改变几何体表面的点的法线使原本是平的东西看起来有凹凸的效果,整个过程并没有真正改变顶点的高度,而是定义了一个虚拟的高度
位移贴图Displacement Mapping:
凹凸贴图是模拟,虚拟的移动,而位移贴图是真的把顶点做了位置的移动
位移贴图更加真实,但是对模型的面数有一定要求,需要有大量的顶点构成
面数低的模型可以通过曲面细分的方法增加面数