大多数情况下,在着色器在 GPU 上运行的程序。 更多信息
参见 术语表中采样纹理时,纹理采样状态应来自纹理设置——本质上,纹理和采样器是耦合在一起的。在使用 DX9 样式着色器语法时,这是默认行为。
sampler2D _MainTex;
// ...
half4 color = tex2D(_MainTex, uv);
使用 sampler2D、sampler3D、samplerCUBE HLSL 关键字声明纹理和采样器。
大多数情况下,这就是你想要的,并且是旧版图形 API(OpenGL ES)上唯一支持的选项。
许多图形 API 和 GPU 允许使用少于纹理的采样器,并且耦合的纹理+采样器语法可能不允许编写更复杂的着色器。例如,Direct3D 11 允许在单个着色器中使用最多 128 个纹理,但最多只能使用 16 个采样器。
Unity 允许使用 DX11 样式 HLSL 语法声明纹理和采样器,并使用特殊的命名约定将它们匹配起来:名称格式为“sampler”+TextureName 的采样器将采用该纹理的采样状态。
上面部分的着色器代码片段可以用 DX11 样式 HLSL 语法重写,并且它会执行相同的操作。
Texture2D _MainTex;
SamplerState sampler_MainTex; // "sampler" + “_MainTex”
// ...
half4 color = _MainTex.Sample(sampler_MainTex, uv);
但是,通过这种方式,可以编写一个着色器来“重用”其他纹理的采样器,同时采样多个纹理。在下面的示例中,采样了三个纹理,但所有纹理都只使用了一个采样器。
Texture2D _MainTex;
Texture2D _SecondTex;
Texture2D _ThirdTex;
SamplerState sampler_MainTex; // "sampler" + “_MainTex”
// ...
half4 color = _MainTex.Sample(sampler_MainTex, uv);
color += _SecondTex.Sample(sampler_MainTex, uv);
color += _ThirdTex.Sample(sampler_MainTex, uv);
Unity 提供了一些着色器宏来帮助使用这种“分离采样器”方法声明和采样纹理,请参阅内置宏。上面的示例可以使用这些宏以这种方式重写。
UNITY_DECLARE_TEX2D(_MainTex);
UNITY_DECLARE_TEX2D_NOSAMPLER(_SecondTex);
UNITY_DECLARE_TEX2D_NOSAMPLER(_ThirdTex);
// ...
half4 color = UNITY_SAMPLE_TEX2D(_MainTex, uv);
color += UNITY_SAMPLE_TEX2D_SAMPLER(_SecondTex, _MainTex, uv);
color += UNITY_SAMPLE_TEX2D_SAMPLER(_ThirdTex, _MainTex, uv);
以上内容将在 Unity 支持的所有平台上编译,但在旧平台(如 DX9)上将回退到使用三个采样器。
除了识别命名为“sampler”+TextureName 的 HLSL SamplerState 对象外,Unity 还识别采样器名称中的一些其他模式。这对于直接在着色器中声明简单的硬编码采样状态很有用。示例如下
Texture2D _MainTex;
SamplerState my_point_clamp_sampler;
// ...
half4 color = _MainTex.Sample(my_point_clamp_sampler, uv);
名称“my_point_clamp_sampler”将被识别为一个采样器,该采样器应使用 Point(最近邻)纹理过滤和 Clamp 纹理环绕模式。
被识别为“内联”采样器状态的采样器名称(全部不区分大小写)
“Point”、“Linear”或“Trilinear”(必需)设置纹理过滤模式。
“Clamp”、“Repeat”、“Mirror”或“MirrorOnce”(必需)设置纹理环绕模式。
“Compare”(可选)为深度比较设置采样器;与 HLSL SamplerComparisonState 类型和 SampleCmp / SampleCmpLevelZero 函数一起使用。
“AnisoX”(其中 X 可以是 2/4/8 或 16,例如,Aniso8
)可以添加到请求各向异性过滤中。
以下是一个分别使用sampler_linear_repeat
和sampler_point_repeat
SamplerState 采样纹理的示例,说明名称如何控制过滤模式。
以下是一个分别使用SmpClampPoint
、SmpRepeatPoint
、SmpMirrorPoint
、SmpMirrorOncePoint
、Smp_ClampU_RepeatV_Point
SamplerState 的示例,说明名称如何控制环绕模式。在最后一个示例中,为水平(U)和垂直(V)轴设置了不同的环绕模式。在所有情况下,纹理坐标范围为 –2.0 到 +2.0。
与分离的纹理+采样器语法一样,内联采样器状态在某些平台上不受支持。目前,它们在 Direct3D 11/12 和 Metal 上已实现。
请注意,“MirrorOnce”纹理环绕模式在大多数移动 GPU/API 上不受支持,并且在不支持的情况下将回退到 Mirror 模式。
请注意,“AnisoX”过滤模式是基于平台功能和所选 API 的最佳尝试。实际值将根据最大支持的各向异性级别进行钳位(包括在不支持各向异性过滤的情况下禁用)。
宏 | 用途 |
---|---|
UNITY_DECLARE_TEX2D(name) |
声明纹理和采样器对。 |
UNITY_DECLARE_TEX2D_NOSAMPLER(name) |
声明没有采样器的纹理。 |
UNITY_DECLARE_TEX2DARRAY(name) |
声明纹理数组采样器变量。 |
UNITY_SAMPLE_TEX2D(name,uv) |
使用给定的纹理坐标从纹理和采样器对中采样。 |
UNITY_SAMPLE_TEX2D_SAMPLER( name,samplername,uv) |
使用来自另一个纹理(samplername)的采样器从纹理(name)中采样。 |
UNITY_SAMPLE_TEX2DARRAY(name,uv) |
使用 float3 UV 从纹理数组中采样;坐标的 z 分量是数组元素索引。 |
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) |
使用显式 mipmap 级别从纹理数组中采样。 |