My own terrane shader is not working

Hi, I’m trying to write a shader for my terrane with quad tesselation. But I have a problem. In what may be the reason, any suggestions? With tri-tessellation mode there is no problem.

Shader "Quad tesselation" {
SubShader {
Pass { Tags {"LightMode" = "Vertex"}

CGPROGRAM
#pragma vertex vert
#pragma hull hull
#pragma domain domain
#pragma fragment frag

#include "UnityCG.cginc"
//=================================================================================================================================
// Shader structures
//=================================================================================================================================

struct VS_INPUT
{
    float3 position : POSITION;
};

struct VS_OUTPUT
{
    float4 position : POSITION;
};

struct HS_CONSTANT_DATA_OUTPUT
{
    float Edges[4]  : SV_TessFactor;
    float Inside[2]    : SV_InsideTessFactor;
};

struct HS_OUTPUT
{
    float3 position : POS;
};

struct DS_OUTPUT
{
    float4 position : SV_Position;
};

//=================================================================================================================================
// Vertex shader
//=================================================================================================================================
VS_OUTPUT vert(VS_INPUT v)
{
    VS_OUTPUT output;
    output.position = mul(UNITY_MATRIX_MV, float4(v.position, 1.0));
    return output;
}

//=================================================================================================================================
// Hull shader
//=================================================================================================================================
HS_CONSTANT_DATA_OUTPUT constantsHS(InputPatch<VS_OUTPUT, 4> patch)
{
    HS_CONSTANT_DATA_OUTPUT output = (HS_CONSTANT_DATA_OUTPUT)0;
    output.Edges[0] = output.Edges[1] = output.Edges[2] = output.Edges[3] = 2;
    output.Inside[0] = output.Inside[1] = 2;
   
    return output;
}

[domain("quad")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(4)]
[patchconstantfunc("constantsHS")]
HS_OUTPUT hull(InputPatch<VS_OUTPUT, 4> patch, uint uCPID: SV_OutputControlPointID)
{
    HS_OUTPUT output = (HS_OUTPUT)0;
    output.position = patch[uCPID].position.xyz;
   
    return output;
}

//=================================================================================================================================
// Domain shader
//=================================================================================================================================
[domain("quad")]
DS_OUTPUT domain(HS_CONSTANT_DATA_OUTPUT input, const OutputPatch<HS_OUTPUT, 4> patch, float2 UV : SV_DomainLocation)
{
    DS_OUTPUT output = (DS_OUTPUT)0;

    float3 topMidpoint = lerp(patch[0].position, patch[1].position, UV.x);
    float3 bottomMidpoint = lerp(patch[3].position, patch[2].position, UV.x);
     float3 pos = lerp(topMidpoint, bottomMidpoint, UV.y);
                       
    output.position = mul(UNITY_MATRIX_P, float4(pos, 1.0));
    return output;
}

//=================================================================================================================================
// Fragment shader
//=================================================================================================================================
float4 frag(DS_OUTPUT f) : COLOR
{
    float4 c;
    c.b = 0.5;
   
    return c;
}

ENDCG
}
}
}

In import mesh settings you must check option “Keep quads” or use MeshTopology.Quads method for procedural generated quad mesh

Your shader works perfectly with quad mesh exported from Modo and imported by “Keep quads”.
Tesselated mesh can be visible in wireframe mode by using following script in Main Camera object from:

I would like to apply distance based or edge length dynamic tessellation factors, depends of distance between camera and vertex positions (lines 58 and 59 of attached code), but I can’t get proper solution. Maybe someone knows how to do it.

Thank you, I have to deal with this issue. Perhaps what you are looking for:

float UnityCalcDistanceTessFactor (float4 vertex, float minDist, float maxDist, float tess)
{
    float3 wpos = mul(_Object2World,vertex).xyz;
    float dist = distance (wpos, _WorldSpaceCameraPos);
    float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0) * tess;
    return f;
}

HS_CONSTANT_DATA_OUTPUT constantsHS(InputPatch<VS_OUTPUT, 4> patch,  uint PatchID : SV_PrimitiveID)
{
    HS_CONSTANT_DATA_OUTPUT output = (HS_CONSTANT_DATA_OUTPUT)0;
   
    tessFactor.x = UnityCalcDistanceTessFactor (patch[0].position, _MinDistance, _MaxDistance, _TessFactor);
    tessFactor.y = UnityCalcDistanceTessFactor (patch[1].position, _MinDistance, _MaxDistance, _TessFactor);
    tessFactor.z = UnityCalcDistanceTessFactor (patch[2].position, _MinDistance, _MaxDistance, _TessFactor);
    tessFactor.w = UnityCalcDistanceTessFactor (patch[3].position, _MinDistance, _MaxDistance, _TessFactor);
       
    output.Edges[0] = max(tessFactor.x, tessFactor.w);
    output.Edges[1] = max(tessFactor.x, tessFactor.y);
    output.Edges[2] = max(tessFactor.y, tessFactor.z);
    output.Edges[3] = max(tessFactor.z, tessFactor.w);
    output.Inside[0] = output.Inside[1] = max(max(tessFactor.x, tessFactor.y), max(tessFactor.z, tessFactor.w));
       
    return output;
}

Reviving this thread and stitching the shader together for someone in the future to come by here.

THIS IS A UNITY QUAD TESSELLATION SHADER WITH DISTANCE FACTOR
I did nothing but stitch the above code together, please give credit to the two above gentlemen if using.

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Quad tessellation" {
    Properties{
        _TessFactor("Tessellation Factor", float) = 2
        _MinDistance("Minimum Distance", float) = 2
        _MaxDistance("Maximum Distance", float) = 2
    }
        SubShader{
            Pass{ Tags{ "LightMode" = "Vertex" }
            CGPROGRAM
    #pragma vertex vert
    #pragma hull hull
    #pragma domain domain
    #pragma fragment frag
    #include "UnityCG.cginc"
        //=================================================================================================================================
        // Shader structures
        //=================================================================================================================================
        float _TessFactor;
        float _MinDistance;
        float _MaxDistance;
        struct VS_INPUT
    {
        float3 position : POSITION;
    };
    struct VS_OUTPUT
    {
        float4 position : POSITION;
    };
    struct HS_CONSTANT_DATA_OUTPUT
    {
        float Edges[4]  : SV_TessFactor;
        float Inside[2]    : SV_InsideTessFactor;
    };
    struct HS_OUTPUT
    {
        float3 position : POS;
    };
    struct DS_OUTPUT
    {
        float4 position : SV_Position;
    };
    //=================================================================================================================================
    // Vertex shader
    //=================================================================================================================================
    VS_OUTPUT vert(VS_INPUT v)
    {
        VS_OUTPUT output;
        output.position = mul(UNITY_MATRIX_MV, float4(v.position, 1.0));
        return output;
    }
    //=================================================================================================================================
    // Hull shader
    //=================================================================================================================================
    float UnityCalcDistanceTessFactor (float4 vertex, float minDist, float maxDist, float tess)
    {
        /// Wrong space to fit with rest of code
        //float3 wpos = mul(unity_ObjectToWorld,vertex).xyz;
        //float dist = distance(wpos, _WorldSpaceCameraPos); 
        // This is just depth in view space. Actual distance to camera is the out-commented, trailing code.
        float dist = -vertex.z;//distance(vertex.xyz, float3(0, 0, 0));
        float f = clamp(1.0 - (dist - minDist) / (maxDist - minDist), 0.01, 1.0) * tess;
        return f;
    }
    HS_CONSTANT_DATA_OUTPUT constantsHS(InputPatch<VS_OUTPUT, 4> patch,  uint PatchID : SV_PrimitiveID)
    {
        HS_CONSTANT_DATA_OUTPUT output = (HS_CONSTANT_DATA_OUTPUT)0;
        float4 tessFactor;
        tessFactor.x = UnityCalcDistanceTessFactor (patch[0].position, _MinDistance, _MaxDistance, _TessFactor);
        tessFactor.y = UnityCalcDistanceTessFactor (patch[1].position, _MinDistance, _MaxDistance, _TessFactor);
        tessFactor.z = UnityCalcDistanceTessFactor (patch[2].position, _MinDistance, _MaxDistance, _TessFactor);
        tessFactor.w = UnityCalcDistanceTessFactor (patch[3].position, _MinDistance, _MaxDistance, _TessFactor);
       
        output.Edges[0] = max(tessFactor.x, tessFactor.w);
        output.Edges[1] = max(tessFactor.x, tessFactor.y);
        output.Edges[2] = max(tessFactor.y, tessFactor.z);
        output.Edges[3] = max(tessFactor.z, tessFactor.w);
        output.Inside[0] = output.Inside[1] = max(max(tessFactor.x, tessFactor.y), max(tessFactor.z, tessFactor.w));
       
        return output;
    }
    [domain("quad")]
    [partitioning("fractional_odd")]
    [outputtopology("triangle_cw")]
    [outputcontrolpoints(4)]
    [patchconstantfunc("constantsHS")]
    HS_OUTPUT hull(InputPatch<VS_OUTPUT, 4> patch, uint uCPID: SV_OutputControlPointID)
    {
        HS_OUTPUT output = (HS_OUTPUT)0;
        output.position = patch[uCPID].position.xyz;
        return output;
    }
    //=================================================================================================================================
    // Domain shader
    //=================================================================================================================================
    [domain("quad")]
    DS_OUTPUT domain(HS_CONSTANT_DATA_OUTPUT input, const OutputPatch<HS_OUTPUT, 4> patch, float2 UV : SV_DomainLocation)
    {
        DS_OUTPUT output = (DS_OUTPUT)0;
        float3 topMidpoint = lerp(patch[0].position, patch[1].position, UV.x);
        float3 bottomMidpoint = lerp(patch[3].position, patch[2].position, UV.x);
        float3 pos = lerp(topMidpoint, bottomMidpoint, UV.y);
        output.position = mul(UNITY_MATRIX_P, float4(pos, 1.0));
        return output;
    }
    //=================================================================================================================================
    // Fragment shader
    //=================================================================================================================================
    float4 frag(DS_OUTPUT f) : COLOR
    {
        float4 c;
    c.b = 0.5;
    return c;
    }
        ENDCG
    }
    }
}