最重要的重点------面对的群体
之所以叫Unity图形学笔记,而不是图形学笔记。
因为本系列重在整理在Unity项目开发过程中,解决一些项目问题所需的图形知识。
与正经的图形学教程不同在于,不再从渲染管线开始讲起,而是每一章讲解某一个问题的所有解决方案。
所以面对的群体,是项目开发中,没有太多图形学基础Unity程序、美术。
本系列来源于作者这几年学习过程中的整理,久远的链接找不到了,请恕无法一一给出引用链接。
问题:
项目开发中,偶尔会遇见如下问题:
UV采样结果自动翻转了?
正文:
纹理:也就是Unity的材质下,显示的 Texture。

它包含两部分:
1.贴图
2.纹理UV,也就是Tilling 、Offset。
纹理UV的默认范围是0-1。
Tiling:缩放模型UV纹理采样坐标,比如Tiling的X = 2, 表示把模型UV坐标的U扩大2倍,U范围变成了0-2
Offset,则代表uv的偏移。
计算公式: uv = uv* Tilling .xy + Offset;
Shader实现:
float4 _MainTex_ST;//纹理缩放偏移向量(Unity默认此变量赋值,变量命名规则:纹理名_ST)
vert()
{
...
//第一种方式:
o.uv = v.vertex.xy * _MainTex_ST.xy + _MainTex_ST.zw;
//第二种方式:使用内建宏,这只是对第一种的封装
o.uv = TRANSFORM_TEX(v.vertex,_MainTex);
}
纹理坐标的UV起始点:
Direct3D里面是左上角为原点:

OpenGL和OpenGL ES是左下角为原点:

屏幕的UV也是左下角为原点:

所以,我们可以看到,DX平台的图片UV与屏幕UV是Y轴对称的。
什么时候不需要理会平台差异?
D3D平台下,有一种情况不需要Unity自动翻转渲染贴图,那就是使用Image Effects和Anti-Aliasing时。
因为Image Effects和Anti-Aliasing 已经是在Screen上操作了。
什么时候Unity会帮我们解决DX平台和Openg平台的差异?
在Render To Texture时,Unity对于D3D平台会自动将渲染的贴图上下翻转一下,以此隐藏了各平台的差异。也就是 Y = 1-Y。
什么时候需要我们自己解决?
需要手动处理的情况:但同时使用screen texture和RenderTexture时,有可能会得到不一致的坐标朝向,此时就需要在shader里面通过代码处理了:
//在D3D上使用AA时,主纹理和 scene depth texture 会以不同的垂直方向出现。
//所以在这种情况下对纹理进行翻转采样(主纹理// texel size 的大小为- Y)。
#if UNITY_UV_STARTS_AT_TOP if (_MainTex_TexelSize.y < 0)
uv.y = 1-uv.y;
#endif
与纹理采样相关的设置 Wrap Mode:

Wrap Mode就是选择纹理平铺时的循环模式,有两种:
1.Repeat 重复, 纹理重复(平铺)本身.
2.Clamp 钳制, 纹理的边缘得到延伸.
编写NGUI(或者其他被打成图集的纹理)的shader
如果用NGUI做shader的话, 要做一个单个UV和图集UV的换算。
如果想直接使用图片UV来做shader特效的,可以不用NGUI组件,用面片来代替。
2.同时采样多个纹理
fbx里可以保留多套uv,
obj里只能保留默认的第一套
unity 目前只支持顶点存 四套uv

在shader编程中,分别叫UV0, UV1, UV2, UV3,而在c#编程中分别叫UV, UV2, UV3, UV4。
所以,在shader和C#中编程,要使用对应的命名。
(从源码上看出来)
namespace UnityEngine.Rendering {
public enum UVChannelFlags {
UV0 = 1,//主纹理
UV1 = 2,//光照贴图
UV2 = 4,//实时动态光照
UV3 = 8//可进行自定义。
}
}
如果一个shader要同时使用多个模型UV,那么命名要求 如下:
sampler2D _MainTex;
sampler2D _Tex_002;
struct v2f {
float4 pos : SV_POSITION;
float2 uv_MainTex : TEXCOORD0;
float2 uv2_Tex_002 : TEXCOORD1;
};
"uv_" +纹理名字
"uv2_" +纹理名字
以此类推
采样精度控制:
- sampler2D, sampler2D_half, sampler2D_float
采样深度贴图这种需要高精度数据时,使用sampler2D_float类型
- samplerCUBE, samplerCUBE_half, samplerCUBE_float
- sampler3D
3.模型导出会有几套UV?
如果在3d模型中只做了一套uv,将模型导入unity的时候,在导入设置中勾选Generate Lightmap UVs, unity会自动为我们生成用于光照贴图的uv1,和用于动态光照的uv2。