Sharpening Terrain blend mask

Hi,
I’m trying to sharpen the blending between terrain textures.

I tried using

splat_control = saturate(pow(splat_control, 100));

This does clamp terrain splat mask to 0/1 values so gradual transition pixels are removed. Problem is this introduces artifacts between textures where those gradual transition pixels should have been.


The saturate(pow()) code works if I use it on normal texture mask, but on mask provided from Control Texture channels it does not work :frowning:

After digging through some other assets i tried to introduce additional parameters.

splat_control = saturate(pow(splat_control*_Pow1, _Pow2));

_Pow1 float lets me reduce the the gap between textures, and _Pow2 helps sharpen it. But no matter what values I use i still get problematic places in transitions.

Has anyone tried something similar? Why does terrain mask behave differently?

I was able to reduce effect further by lerping textures in Firstpass shader instead of adding them. But when I tried same in AddPass shader that didn’t work.

I tried some work arounds.
I can’t increase the control texture resolution as that impacts my performance greatly and I already use multiple terrains. I end up with 64 terrain chunks 65mb each and 4GB load in memory(250x250, Control texture resolution 2048) to get transition quality I want. Even with limiting chunks through streaming performance is not that great with that setup.
I looked at CTS terrain shaders plugin and microsplat, I cant use them because I have custom shader with some toon effects and implementing them in those shaders is far beyond my skill. They also suffer from same problems as me with reduced sharpness(although to much lesser extent)

ive tried this in 2 different ways,
setting texture filtermode,

adjusting shader with a huge if list…

@mgear

Hey, thank you.
I think if makes it super slow. But filtering mode did help me understand something more.

here is splat map with trilinear textures (with lerp method applied)

Here is same with point textures

See the three semi transparent pixels between gravel and snow? I think those get deleted from the splat map completely with pow and this causes them to be black somehow during addition of splats, and show first splat map during lerp blending of splats.

I also exported splat map and added bunch over overlays on it to simulate pow. and Lo and behold black spots:

Not sure how to get around this.

ok a friend help me with something like this if anyone is interested

    half transformSplat(half splatChannel, half breakup){
        splatChannel = saturate(splatChannel / breakup);
        return saturate(pow(splatChannel, 5));
    }
   
    // Surface Shader function
    void surf (Input IN, inout SurfaceOutput o) {
        float4 splat_control = tex2D (_Control, IN.uv_Control);

        // added breakup texture
        // half2(10, 3) -- is just X-Y tiling multiplier for breakup texture
        fixed breakup = tex2D(_Breakup, IN.uv_Control * half2(10, 3));   

       
         fixed r = transformSplat(splat_control.r, breakup);
         fixed g = transformSplat(splat_control.g, breakup);
         fixed b = transformSplat(splat_control.b, breakup);
         fixed a = transformSplat(splat_control.a, breakup);
 

        half3 lerpedCol = tex2D(_Splat0, IN.uv_Splat0);
        //half3 lerpedCol = half3(0, 0, 0);
        lerpedCol = lerp(lerpedCol,  tex2D (_Splat0, IN.uv_Splat0).rgb, r);
        lerpedCol = lerp(lerpedCol, tex2D(_Splat1, IN.uv_Splat1).rgb, g);
        lerpedCol = lerp(lerpedCol, tex2D(_Splat2, IN.uv_Splat2).rgb, b);
        lerpedCol = lerp(lerpedCol, tex2D(_Splat3, IN.uv_Splat3).rgb, a);

        o.Albedo = lerpedCol;
        o.Alpha = 1;
    }

you just need to define breakup texture
in Add pass same thing except change surf decal:add to decal:blend
and change o.Alpha = 1 to o.Alpha = saturate(splat_control.r + splat_control.g + splat_control.b + splat_control.a);

now depending on breakup texture you assign you should get different blends with minimal artifacts.