0
\$\begingroup\$

Well, I have this triplanar shader:

Shader "Custom/z3nth10n/Tests/MultiTriplanar" {
    Properties {
        _MainTex ("Main Texture", 2D) = "white" { }
        _Top ("Top Main Texture", 2DArray) = "" { }
        _TopHeightmap ("Top Heightmap Texture", 2DArray) = "" { }
        _TopNormal ("Top Normal Texture", 2DArray) = "" { }
        _Side ("Side Main Texture", 2DArray) = "" { }
        _SideHeightmap ("Side Heightmap Texture", 2DArray) = "" { }
        _SideNormal ("Side Normal Texture", 2DArray) = "" { }
        _Color ("Color", Color) = (1, 1, 1, 1)
        _Glossiness ("Smoothness", Range(0, 1)) = 0.5
        _Metallic ("Metallic", Range(0, 1)) = 0.0
        _Occlusion ("Occlusion", Range(0, 1)) = 1.0
        _Tiling ("Tiling", Float) = 0.5
    }
    
    SubShader {
        Tags { "RenderType" = "Opaque" }
        LOD 200
        Offset[_ZOffset], [_ZOffset]

        CGPROGRAM
        #pragma surface surf Standard vertex:vert
        #pragma vertex vert
        #pragma require 2darray
        #pragma target 3.5
        
        #include "UnityCG.cginc"
        
        sampler2D _MainTex;

        UNITY_DECLARE_TEX2DARRAY(_Top);
        UNITY_DECLARE_TEX2DARRAY(_Side);
        UNITY_DECLARE_TEX2DARRAY(_TopHeightmap);
        UNITY_DECLARE_TEX2DARRAY(_SideHeightmap);
        UNITY_DECLARE_TEX2DARRAY(_TopNormal);
        UNITY_DECLARE_TEX2DARRAY(_SideNormal);

        struct Input {
            float2 uv_MainTex;
            float3 worldPos;
            float3 worldNormal;

            INTERNAL_DATA
        };

        float4 _MainTex_TexelSize;

        float _DisplacementStrength;
        float _DisplacementStrength2;

        half _Glossiness, _Metallic, _Tiling, _Occlusion;
        fixed4 _Color;

        void vert(inout appdata_full v, out Input o) {
            UNITY_INITIALIZE_OUTPUT(Input, o);

            o.worldPos = v.texcoord;
            o.worldNormal = v.normal;
        }

        float3 getAlbedo(Input IN, int arrayIndex) {
            float3 xAlbedo = UNITY_SAMPLE_TEX2DARRAY(_Side, float3(frac(IN.worldPos.zy * _Tiling), arrayIndex)) * abs(IN.worldNormal.x);
            float3 yAlbedo = UNITY_SAMPLE_TEX2DARRAY(_Top, float3(frac(IN.worldPos.zx * _Tiling), arrayIndex)) * abs(IN.worldNormal.y);
            float3 zAlbedo = UNITY_SAMPLE_TEX2DARRAY(_Side, float3(frac(IN.worldPos.xy * _Tiling), arrayIndex)) * abs(IN.worldNormal.z);

            float3 projNormal = saturate(pow(IN.worldNormal * 1.4, 4));

            float3 texAlbedo = zAlbedo;
            texAlbedo = lerp(texAlbedo, xAlbedo, projNormal.x);
            texAlbedo = lerp(texAlbedo, yAlbedo, projNormal.y);

            return texAlbedo;
        }

        void surf(Input IN, inout SurfaceOutputStandard o) {
            // https://gamedev.stackexchange.com/a/186384/76780
            float2 rightNeighbour = IN.uv_MainTex + float2(_MainTex_TexelSize.x, 0);
            float2 leftNeighbour = IN.uv_MainTex - float2(_MainTex_TexelSize.x, 0);
            float2 topNeighbour = IN.uv_MainTex + float2(0, _MainTex_TexelSize.y);
            float2 bottomNeighbour = IN.uv_MainTex - float2(0, _MainTex_TexelSize.y);

            float4 texCenter = tex2D(_MainTex, IN.uv_MainTex);
            float4 texRight = tex2D(_MainTex, rightNeighbour);
            float4 texLeft = tex2D(_MainTex, leftNeighbour);
            float4 texTop = tex2D(_MainTex, topNeighbour);
            float4 texBottom = tex2D(_MainTex, bottomNeighbour);

            int arrayIndex0 = min(255, max(floor(texCenter.a * 255), 0));
            int arrayIndex1 = min(255, max(floor(texRight.a * 255), 0));
            int arrayIndex2 = min(255, max(floor(texLeft.a * 255), 0));
            int arrayIndex3 = min(255, max(floor(texTop.a * 255), 0));
            int arrayIndex4 = min(255, max(floor(texBottom.a * 255), 0));

            float3 albedo0 = getAlbedo(IN, arrayIndex0);
            float3 albedo1 = getAlbedo(IN, arrayIndex1);
            float3 albedo2 = getAlbedo(IN, arrayIndex2);
            float3 albedo3 = getAlbedo(IN, arrayIndex3);
            float3 albedo4 = getAlbedo(IN, arrayIndex4);

            o.Albedo =
                (albedo0.rgb * _Color) * 0.2 +
                (albedo1.rgb * _Color) * 0.2 +
                (albedo2.rgb * _Color) * 0.2 +
                (albedo3.rgb * _Color) * 0.2 +
                (albedo4.rgb * _Color) * 0.2;

            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Occlusion = _Occlusion;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

As you can see, I linked this answer which gives me the solution to get the neighbor UVs. The idea behind this is that I could get the different arrayIndexes from the main texture (from their alpha channel) by looking up from their 4 neighbor and mixing their rgb (by multiplying per 0.2 or the same that dividing it by 5, because we have the center texture + 4 neighbors).

I would like to change this part, by smoothing it.

            o.Albedo =
                (albedo0.rgb * _Color) * 0.2 +
                (albedo1.rgb * _Color) * 0.2 +
                (albedo2.rgb * _Color) * 0.2 +
                (albedo3.rgb * _Color) * 0.2 +
                (albedo4.rgb * _Color) * 0.2;

Because of this result:

...

I would like to smooth these transitions, they are too "square". I tried to use UVs rotation/displacement, in the vert function:

    float random(float2 uv) {
        return frac(sin(dot(uv, float2(12.9898, 78.233))) * 43758.5453123);
    }

Vert function:

        float r = random(v.texcoord);

        float sinX = sin(r * _DisplacementStrength);
        float cosX = cos(r * _DisplacementStrength);
        float sinY = sin(r * _DisplacementStrength);
        float2x2 rotationMatrix = float2x2(cosX, -sinX, sinY, cosX);

        v.texcoord.xy = frac(mul(v.texcoord.xy, rotationMatrix);

But this outputs this:

...

It is useful, but I still can see the different albedos being mixed. How could I smooth these transitions?

\$\endgroup\$
2
  • \$\begingroup\$ @DMGregory well, I did what you suggested. I edited this topic. The only point that I don't "like", is the comment history from the topic. \$\endgroup\$
    – z3nth10n
    Commented Jul 2 at 10:49
  • 1
    \$\begingroup\$ That's easy to clean up, as shown. \$\endgroup\$
    – DMGregory
    Commented Jul 2 at 12:16

0

You must log in to answer this question.

Browse other questions tagged .