使用采样器声明

耦合的材质和取样器

大多数情况下,在shader中采样贴图时,贴图采样声明应该来自贴图设置-本质上,贴图和采样器是被绑在一起的。在用DX9风格 shader 语法时,这是一个默认行为:

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

使用 sampler2D,sampler3D,samplerCUBE HLSL关键字同时声明贴图和取样器。

大多数情况下这是你想要的,但是这只在老图形API上才支持(OpenGL ES)。

分别的材质和取样器

大部分图形API和CPU允许贴图比采样器多,并且耦合的贴图+采样器在写复杂的shader时可能是不允许的。比如在D3D 11中一个shader中可以使用128张贴图,但是最多却只有16个采样器。

unity允许声明贴图和采样器时使用DX11风格的HLSL语法,用一个特殊的命名惯例来将他们匹配起来;拥有名字为“sampler”+贴图名字 的采样器会对这个纹理进行取样。

上面描述的语法如下:

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

但是请注意,dx11风格的HLSL语法在一些较旧的平台上不起作用(比如OpenGL ES2.0),在 shading language查看细节。你可能需要声明 #pragma target 3.5 来跳过老的平台使用shader。

unity提供几个shader宏命令来帮助声明和采样贴图使用这个“分离的采样器”方法,查看 built-in macros.上面的例子可以被重写为下面的样子:

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” or “Trilinear” (必须) 设置贴图过滤模式。
  • “Clamp”, “Repeat”, “Mirror” or “MirrorOnce” (必须)设置贴图覆盖模式。
  • 贴图覆盖模式可以指定每个轴向(UVW),比如:“ClampU_RepeatV”。
  • “比较”(可选择的)设置采样器深度比较;使用HLSL 采样器比较声明类型和 SampleCmp / SampleCmpLevelZero 函数。

这里有一个抽样纹理的例子,sampler_linear_repeat和sampler_point_repeat SamplerStates分别说明了名称控制过滤模式的方式:

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

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

注意,在大多数移动gpu / api上,“MirrorOnce”纹理包装模式不受支持,当支持不存在时,它将返回镜像模式。

 

posted @ 2018-02-23 17:45  gameDesigner  阅读(2793)  评论(0编辑  收藏  举报