Shader question regarding painting on terrain with custom material

Hey guys,
This is my first post, so please be gentle :stuck_out_tongue: Also, hi!
So I have the following shader that is attached to the custom material I am using for my terrain:

Shader "Custom/Chapter03/RadiusShader"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}

        _Center("Center", Vector) = (200, 0, 200, 0)
        _Radius("Radius", Float) = 100        // Float with capital 'F'
        _RadiusColor("Radius Color", Color) = (1, 0, 0, 1)
        _RadiusWidth("Radius Width", Float) = 10
    }

    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }

        LOD 200

        CGPROGRAM
        // Physically based Standard lighting model, and enable shadows on all light types
        #pragma surface surf Standard fullforwardshadows

        // Use shader model 3.0 target, to get nicer looking lighting
        #pragma target 3.0

        sampler2D _MainTex;
        fixed4 _Color;

        float3 _Center;
        float _Radius;
        float4 _RadiusColor;
        float _RadiusWidth;

        struct Input
        {
            float2 uv_MainTex;    // Terrain texture UV
            float3 worldPos;    // In-world position
        };

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // Get distance between the center of the place we
            // wish to draw from and the input's world pos
            float d = distance(_Center, IN.worldPos);

            // If distance greater than radius and less than
            // our radius + width then change color
            if ((d > _Radius) && (d < (_Radius + _RadiusWidth)))
            {
                o.Albedo = _RadiusColor;
            }
            // Else, use normal color
            else
            {
                o.Albedo = tex2D(_MainTex, IN.uv_MainTex).rgb;
            }
        }

        ENDCG
    }

    FallBack "Diffuse"
}

This (combined with a short script that needs to be attached to the relevant object) creates a circle under that object, that adapts to the terrain surface.
Could you please help me understand what needs to be added so that I can paint on the terrain? I am still trying to get my head around shaders and any help would be immensely appreciated.

Thanks in advance!

1 Like

Oh boy. Terrain materials are extra “fun” because they’re kind of complex and almost competely undocumented.

I would do a google search for Unity custom terrain shaders, there are a couple of examples and even basic tutorials on the topic to look at. The few people I know of to really crack them are those who have terrain shaders on the asset store.

Now, once you do have a custom terrain shader, one that supports multiple texture layers, you’re going to have to add your circle drawing code to both the base and add passes, or limit yourself to no more than 4 (or 5?) terrain layers as there’s no easy way to know how many layers the terrain has.

The “easy” solution may be too use a projector, though those don’t support lighting. The next easiest method would be to add your shader as an extra pass in the terrain shader. I believe there’s a terrain shader example out there that adds a toon outline with an extra pass like that.

Ha, yeah tell me about it!

I was thinking of having two passes (in theory) and what you suggested kinda confirms that, which really helps. I’ve downloaded Unity’s terrain shaders and will give it a go.

Haven’t tried the projector solution at all, as I really want to understand how to use shaders, but will have a look as I’ve seen it mentioned elsewhere. Btw, I know the shader example you mentioned, very helpful article that one.

Thanks for the help!