Version: 2021.2
着色器数据类型和精度
Unity 中的 GLSL

使用采样器状态

耦合的纹理和采样器

Most of the time when sampling textures in shaders, the texture sampling state should come from texture settings – essentially, textures and samplers are coupled together. This is default behavior when using DX9-style shader syntax:

sampler2D _MainTex;
// ...
half4 color = tex2D(_MainTex, uv);

使用 HLSL 关键字 sampler2D、sampler3D 和 samplerCUBE 可声明纹理和采样器。

大部分情况下,这是您想要的结果,而且在较旧的图形 API (OpenGL ES) 中,这是唯一受支持的选项。

单独的纹理和采样器

Many graphics APIs and GPUs allow using fewer samplers than textures, and coupled texture+sampler syntax might not allow more complex shaders to be written. For example, Direct3D 11 allows using up to 128 textures in a single shader, but only up to 16 samplers.

Unity 允许使用 DX11 风格的 HLSL 语法来声明纹理和采样器,但需要通过一个特殊的命名约定来让它们匹配:名称为“sampler”+TextureName 格式的采样器将从该纹理中获取采样状态。

以上部分中的着色器代码片段可以用 DX11 风格的 HLSL 语法重写,并且也会执行相同的操作:

Texture2D _MainTex;
SamplerState sampler_MainTex; //"sampler"+"_MainTex"
// ...
half4 color = _MainTex.Sample(sampler_MainTex, uv);

However, this way, a shader could be written to “reuse” samplers from other textures, while sampling more than one texture. In the example below, three textures are sampled, but only one sampler is used for all of them:

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);

但是请注意,DX11 风格的 HLSL 语法在某些较旧的平台(例如,OpenGL ES 2.0)上无效,请参阅在 Unity 中使用 HLSL 以了解详细信息。您可能需要指定 #pragma target 3.5(请参阅着色器编译目标)以避免较旧的平台使用着色器。

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”、“Linear”或“Trilinear”(必需)设置纹理过滤模式。

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

* 可根据每个轴 (UVW) 来指定包裹模式,例如"ClampU_RepeatV"。

*“Compare”(可选)设置用于深度比较的采样器;与 HLSL SamplerComparisonState 类型和 SampleCmp/SampleCmpLevelZero 函数配合使用。

  • “AnisoX” (where X can be 2/4/8 or 16, for example, Ansio8) can be added to request anisotropic filtering.

以下是分别使用 sampler_linear_repeatsampler_point_repeat 采样器状态进行纹理采样的示例,说明了如何通过名称控制过滤模式:

Here’s an example with SmpClampPoint, SmpRepeatPoint, SmpMirrorPoint, SmpMirrorOncePoint, Smp_ClampU_RepeatV_Point SamplerStates respectively, illustrating how the name controls wrapping mode. In the last example, different wrap modes are set for horizontal (U) and vertical (V) axes. In all cases, texture coordinates go from –2.0 to +2.0.

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

Note that “MirrorOnce” texture wrapping mode is not supported on most mobile GPUs/APIs, and will fallback to Mirror mode when support is not present.

Note that the “AnisoX” filtering modes are a best effort based on the platform capabilities and selected API. The actual value will be clamped based on the maximum supported anisotropic level (including disabled in cases where no anisotropic filtering is supported).


  • 2017–06–01 页面已发布

  • 2017.1 中的新功能 NewIn20171

着色器数据类型和精度
Unity 中的 GLSL