Version: 6000.3
语言: 中文
将顶点数据输入着色器
在着色器中包含另一个 HLSL 文件

纹理采样器

大多数情况下,在着色器在 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”将被识别为应使用点(最近)纹理筛选和钳制纹理包装模式的采样器。

被识别为“内联”采样器状态的采样器名称(所有不区分大小写):

  • “点”、“线性”或“三线性”(必填)设置纹理过滤模式。

  • “Clamp”、“Repeat”、“Mirror”或“MirrorOnce”(必填)设置纹理包裹模式。

    • 可以指定每轴 (UVW) 的包裹模式,例如“ClampU_RepeatV”。
  • “比较”(可选)设置采样器进行深度比较;与 HLSL SamplerComparisonState 类型和 SampleCmp / SampleCmpLevelZero 函数一起使用。

  • “AnisoX”(其中 X 可以是 2/4/8 或 16,例如Aniso8)可以添加来请求各向异性滤波。

下面是使用sampler_linear_repeatsampler_point_repeatSamplerStates,说明名称如何控制筛选模式:

左:用sampler_linear_repeat对纹理进行采样。右图:用sampler_point_repeat对纹理进行采样。
左:对纹理进行采样sampler_linear_repeat.右图:对纹理进行采样sampler_point_repeat.

这是一个示例SmpClampPoint,SmpRepeatPoint,SmpMirrorPoint,SmpMirrorOncePoint,Smp_ClampU_RepeatV_PointSamplerStates,说明名称如何控制包装模式。在最后一个示例中,为水平 (U) 和垂直 (V) 轴设置了不同的环绕模式。在所有情况下,纹理坐标都从 –2.0 到 +2.0。

不同采样器状态如何工作的图示。从左到右:SmpClampPoint、SmpRepeatPoint、SmpMirrorPoint、SmpMirrorOncePoint Smp_ClampU_RepeatV_Point。
不同采样器状态如何工作的图示。从左到右:SmpClampPoint,SmpRepeatPoint,SmpMirrorPoint,SmpMirrorOncePoint,Smp_ClampU_RepeatV_Point.

就像单独的纹理 + 采样器语法一样,某些平台不支持内联采样器状态。目前,它们在 Direct3D 11/12 和 Metal 上实现。

请注意,大多数移动 GPU/API 不支持“MirrorOnce”纹理包装模式,当不支持时,它将回退到镜像模式。

请注意,“AnisoX”过滤模式是基于平台功能和所选 API 的最佳选择。实际值将根据支持的最大各向异性水平进行限制(包括在不支持各向异性过滤的情况下禁用)。

纹理/采样器声明宏

宏观: 用:
UNITY_DECLARE_TEX2D(name) 声明纹理和采样器对。
UNITY_DECLARE_TEX2D_NOSAMPLER(name) 声明不带采样器的纹理。
UNITY_DECLARE_TEX2DARRAY(name) 声明纹理数组采样器变量。
UNITY_SAMPLE_TEX2D(name,uv) 使用给定的纹理坐标从 Texture 和 Sampler 对中采样。
UNITY_SAMPLE_TEX2D_SAMPLER( name,samplername,uv) 从纹理(名称)采样,使用另一个纹理(采样器名称)中的采样器。
UNITY_SAMPLE_TEX2DARRAY(name,uv) 从具有float3 UV的纹理数组中采样;坐标的 z 分量是数组元素索引。
UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod) 从具有显式 mipmap 级别的纹理数组中采样。
将顶点数据输入着色器
在着色器中包含另一个 HLSL 文件