第七章 基础纹理
导言
在OpenGL里,纹理空间的原点位于左下角,而在DirectX中,原点位于左上角。Unity中使用的纹理空间是符合OpenGL的传统的,位于纹理左下角。
一、单张纹理
通常使用一张纹理来代替物体的漫反射颜色。
纹理导入面板
- Filter Mode ,代表纹理拉伸时的滤波模式,支持3种模式: Point、Bilinear、Trilinear;效果依次增加。
- 纹理缩小时,多个像素将会对应一个目标像素。我们往往需要处理抗锯齿问题。一个最常用的方法是使用多级渐远纹理(mipmapping)技术。即提前用了滤波处理得到了更多更小的图像,储存起来。运行时,可以直接使用。通常需要多占用33%的空间。
- Point:使用最近邻滤波,在放大或缩小时,采样像素数目通常只有一个,一次图像看起来有种像素风格。
- Bilinear:使用线性滤波,对于每个目标像素,它会找到4个近邻像素,然后对它们进行线性插值混合后得到的最终像素,因此图像看起来被模糊了。
- Trilinear:除了Bilinear所做的工作之外,还会在多级渐远纹理之间进行混合。
- 纹理的最大尺寸:unity允许不同平台发布游戏时,选择不同的分辨率。如果导入的纹理大小超过了Max Texture Size中的设置值,那么unity将会把该纹理缩放为这个最大分辨率。理想情况下,导入的纹理可以是非正方形的,但长宽的大小应该是2的幂。这样unity内部才能进行压缩,而且GPU读取该纹理的速度更快。
二、凹凸映射
两种凹凸映射做法
- 高度映射:使用一张高度纹理来模拟表面位移,然后得到一个修改后的法线值。优点是直观,缺点是消耗运行时性能。高度纹理更多用来存储地形信息。高度图中存储的是强度值,表示模型表面局部的海拔高度。
- 法线映射:直接存储表面法线信息,由于法线方向的分量范围在[-1, 1],而像素的分量范围是[0,1],因此我们需要做一个映射,通常使用的映射就是。所以我们从法线纹理进行采样后,需要进行一次反映。
模型空间法线纹理 VS 切线空间法线纹理:
- 模型空间优点:
- 实现简单,直观;
- 在纹理坐标的缝合处和尖锐的边角部分,可见的突变较少;
- 切线空间的优点:
- 纹理可复用;
- 可进行UV动画;
- 可压缩;
Unity中的法线纹理类型
- Unity可以把法线纹理标识成Normal map类型,此时可以使用shader中内置的UnpackNormal函数,来得到正确的法线方向。
- 当我们把纹理类型设置为Normal map,可以让Unity根据不同平台对纹理进行压缩(DXT5nm)。原理就是发现纹理只有两个通道是真正具有信息的,第三个通道的值可以用另外两个推导出来(法线是单位向量,切线空间下的法线方向的Z分量为正)。
三、 渐变纹理
使用渐变纹理来控制漫反射光照的结果。
- 书本这里使用半兰伯特模型,计算UV坐标。书里没有明说这么做的理由是什么,这里部分是我自己思考的。我们的目的是得到颜色分层的结果。观察渐变纹理,我们发现色带前面的对应阴影部分,后面对应光照强烈的部分。所以每个片元收到的光照越强,就应该对应色带值大的分。正好半兰伯特模型也是这样,受到的光照越强,得到的值越大。就这样应用过来了。
- 注意:渐变纹理的Weap Mode需要设置为Clamp模型,防止纹理采样时由于浮点数精度造成问题。
四、遮罩纹理
遮罩纹理,字面翻译就是通过遮罩保护某些区域,使它免于某些修改。比如书中例子的高光遮罩纹理,在纹理RGBA的R分量里储存了mask值。在shader中通过下面的语句使用。采样了遮罩纹理,然后将值乘在原高光分量上。用来控制高光的强度。
// Get the mask value
fixed specularMask = tex2D(_SpecularMask, i.uv).r * _SpecularScale;
// Compute specular term with the specular mask
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss) * specularMask;
- 其实看到这里我们已经发现了,我们想逐像素的控制表面属性。就把对应像素的参数都填充在一个纹理里,在shader中参与计算就行了。通常,我们可以充分利用一张纹理的RGBA四个通道,用于储存不同的表面属性参数。
引用
- 如何创建法线贴图
- Unity Shader入门精要 阅读笔记十