如何在使用 Triplanar 时仅将法线贴图应用于一侧?

How do I apply a normalmap to only one side while using Triplanar?

我用的是unity

我使用 Triplanar 将立方体的顶部设为雪地地形,将其余侧面设为悬崖地形。

这里要插入法线贴图

但是,如果应用法线贴图,悬崖面的图像会被雪地图像覆盖。

现象如下图所示

Properties
    {
        [NoScaleOffset]_MainTex ("TopTex", 2D) = "white" {}
        _MainTexUV("tileU, tileV, offsetU, offsetV", vector) = (1, 1, 0, 0)
        [NoScaleOffset]_MainTex2("sideTex", 2D) = "white" {}
        _MainTex2UV("tileU, tileV, offsetU, offsetV", vector) = (1, 1, 0, 0)
        _Bumpmap ("NormalMap", 2D) = "bump" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }

        CGPROGRAM
        #pragma surface surf Standard fullforwardshadows

        sampler2D _MainTex;
        sampler2D _MainTex2;
        sampler2D _Bumpmap;

        float4 _MainTexUV;
        float4 _MainTex2UV;

        struct Input
        {
            float2 uv_Bumpmap;
            float3 worldPos;
            float3 worldNormal;
            INTERNAL_DATA
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            float2 topUV = float2(IN.worldPos.x, IN.worldPos.z);
            float2 frontUV = float2(IN.worldPos.x, IN.worldPos.y);
            float2 sideUV = float2(IN.worldPos.z, IN.worldPos.y);

            o.Normal = UnpackNormal(tex2D(_Bumpmap, IN.uv_Bumpmap));

            float4 topTex = tex2D(_MainTex, topUV * _MainTexUV.xy + _MainTexUV.zw);
            float4 frontTex = tex2D (_MainTex2, frontUV * _MainTex2UV.xy + _MainTex2UV.zw);
            float4 sideTex = tex2D (_MainTex2, sideUV * _MainTex2UV.xy + _MainTex2UV.zw);

            o.Albedo = lerp(topTex, frontTex, abs(IN.worldNormal.z));
            o.Albedo = lerp(o.Albedo, sideTex, abs(IN.worldNormal.x));
            o.Alpha = 1;
        }
        ENDCG
    }
    FallBack "Diffuse"

为什么会这样?

此外,如何将法线贴图仅应用于一侧?

根据the documentation,如果你修改o.Normal;

,你需要使用WorldNormalVector(IN, o.Normal)而不是IN.worldNormal

并且,要仅将法线应用于一侧,您可以简单地对另一侧使用中性法线 (.5,.5,1),并使用与反照率相同的 lerp 技巧:

Properties
{
    [NoScaleOffset] _MainTex("TopTex", 2D) = "white" {}
    _MainTexUV("tileU, tileV, offsetU, offsetV", vector) = (1, 1, 0, 0)
    [NoScaleOffset]_MainTex2("sideTex", 2D) = "white" {}
    _MainTex2UV("tileU, tileV, offsetU, offsetV", vector) = (1, 1, 0, 0)
    _Bumpmap("NormalMap", 2D) = "bump" {}
}
    SubShader
{
    Tags { "RenderType" = "Opaque" }

    CGPROGRAM
    #pragma surface surf Standard fullforwardshadows

    sampler2D _MainTex;
    sampler2D _MainTex2;
    sampler2D _Bumpmap;

    float4 _MainTexUV;
    float4 _MainTex2UV;

    struct Input
    {
        float2 uv_Bumpmap;
        float3 worldPos;
        float3 worldNormal;
        INTERNAL_DATA
    };

    void surf(Input IN, inout SurfaceOutputStandard o)
    {
        float2 topUV = float2(IN.worldPos.x, IN.worldPos.z);
        float2 frontUV = float2(IN.worldPos.x, IN.worldPos.y);
        float2 sideUV = float2(IN.worldPos.z, IN.worldPos.y);

        float3 worldNormal = WorldNormalVector(IN, o.Normal);

        float3 topNormal = float3(.5, .5, 1);
        float3 frontNormal = float3(.5, .5, 1);
        float3 sideNormal = UnpackNormal(tex2D(_Bumpmap, IN.uv_Bumpmap));

        o.Normal = lerp(topNormal, frontNormal, abs(worldNormal.z));
        o.Normal = lerp(o.Normal, sideNormal, abs(worldNormal.x));

        float4 topTex = tex2D(_MainTex, topUV * _MainTexUV.xy + _MainTexUV.zw);
        float4 frontTex = tex2D(_MainTex2, frontUV * _MainTex2UV.xy + _MainTex2UV.zw);
        float4 sideTex = tex2D(_MainTex2, sideUV * _MainTex2UV.xy + _MainTex2UV.zw);

        o.Albedo = lerp(topTex, frontTex, abs(worldNormal.z));
        o.Albedo = lerp(o.Albedo, sideTex, abs(worldNormal.x));

        o.Alpha = 1;
    }
    ENDCG
}
    FallBack "Diffuse"