Unity Shader - 纹理与采样器的分离定义测试

在以前旧版DX9的HLSL是纹理与采样器成对耦合的定义的

如:

sampler2D _Tex;

在DX9中上面就定义了一个纹理,一个采样器
但我们现代的比较多的GPU都是在一个shader可以支持128个纹理,而采样器,可能就16个
如果沿用DX9就这方式来定义就无法超过16个纹理了,因为采样器会一并定义。

在DX10后,就有优化了,可以将纹理,采样器分开了定义了

这样我们就可以在多张纹理采样时使用指定的采样器
在我们下面的例子:三个纹理采样时使用同一个采样器

具体,可看看之前翻译的Using sampler states 使用采样器的状态

Shader

// jave.lin 2019.07.03
Shader "Test/TestMultiSampler"
{
    Properties
    {
        [KeywordEnum(SamplerMacro, DIY)] _SMP ("Sampler Snippet type", Float) = 0
        _tex1 ("tex1", 2D) = "white" {}
        [NoScaleOffset] _tex2 ("tex2", 2D) = "white" {}
        [NoScaleOffset] _tex3 ("tex3", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Pass
        {
            CGPROGRAM
            #pragma multi_compile _SMP_SAMPLERMACRO _SMP_DIY
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
            };
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
            };
            #if _SMP_SAMPLERMACRO
            UNITY_DECLARE_TEX2D(_tex1);
            UNITY_DECLARE_TEX2D_NOSAMPLER(_tex2);
            UNITY_DECLARE_TEX2D_NOSAMPLER(_tex3);
            #else
            Texture2D _tex1;
            Texture2D _tex2;
            Texture2D _tex3;
            //#define smp sampler_tex1 // 使用unity的texture setting的sampler
            //#define smp sampler_linear_clampu // filter:linear, wrap: clamp u
            //#define smp sampler_linear_clampv // filter:linear, wrap: clamp v
            //#define smp sampler_point_clamp // filter:point, wrap: clamp u & v
            //#define smp sampler_linear_clamp // filter:linear, wrap: clamp u & v
            //#define smp sampler_trilinear_clamp // filter:trilinear, wrap: clamp u & v
            //#define smp sampler_trilinear_mirroru // filter:trilinear, wrap: mirror u
            //#define smp sampler_trilinear_mirrorv // filter:trilinear, wrap: mirror v
            //#define smp sampler_trilinear_mirror // filter:trilinear, wrap: mirror v & v
            //#define smp sampler_trilinear_mirroronceu // filter:trilinear, wrap: mirror once u, 这个亲测法线mirror v也生成,不知道是否解析的BUG
            //#define smp sampler_trilinear_mirroroncev // filter:trilinear, wrap: mirror once v, 这个亲测法线mirror u也生成,不知道是否解析的BUG
            //#define smp sampler_trilinear_mirroroncev_mirroru // filter:trilinear, wrap: mirror once v & mirror u, 亲测两个一起设置,就没有BUG
            //#define smp sampler_trilinear_mirroru_repeat // filter:trilinear, wrap: mirror u & repeat v
            #define smp sampler_trilinear_mirroru_clamp // filter:trilinear, wrap: mirror u & repeat v
            SamplerState smp;
            #endif
            float4 _tex1_ST;
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _tex1);
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                #if _SMP_SAMPLERMACRO
                half3 tc1 = UNITY_SAMPLE_TEX2D(_tex1, i.uv);
                half3 tc2 = UNITY_SAMPLE_TEX2D_SAMPLER(_tex2, _tex1, i.uv);
                half3 tc3 = UNITY_SAMPLE_TEX2D_SAMPLER(_tex3, _tex1, i.uv);
                #else
                half3 tc1 = _tex1.Sample(smp, i.uv);
                half3 tc2 = _tex2.Sample(smp, i.uv);
                half3 tc3 = _tex3.Sample(smp, i.uv);
                #endif
                half4 combined = fixed4(tc1 * tc2 + tc3, 1);
                return combined;
            }
            ENDCG
        }
    }
}

我们使用#pragma multi_compile区别了两种方式

#pragma multi_compile _SMP_SAMPLERMACRO _SMP_DIY

第一种是使用UNITY内置的方式,这种方式是使用Unity编辑器中对纹理设置的配置来定义采样器状态的,如,在Project视图,选择中一个纹理,设置了它的Filter为Point,那么这个宏定义默认就会使用你刚刚定义的纹理配置:Filter:Point。

第二种是手动编写的方式,这种方式在之前翻译的Using sampler states 使用采样器的状态,有提到,叫Inline Sampler States,内联方式,Unity会对名称进行识别,对linear,point,trilinear,clamp,mirror,mirroronce,repeat等,都可以识别,然后自动给你这个按名称定义的采样器,自动设置上对应的采样状态属性。

上面的名称的识别的字,大小写不敏感的,按你喜欢方式来写即可。

也可以看到手动写的第一行注释掉的方式:

Texture2D _tex1;
...
#define smp sampler_tex1 // 使用unity的texture setting的sampler

这个方式和第一种使用的方式是一样的
注释的代码中,可以看到有好多种配置组合定义的方式,按你需要的来即可

运行效果

Unity Shader - 纹理与采样器的分离定义测试_第1张图片

你可能感兴趣的:(unity,unity-shader)