Need help with clip function in HLSL

So I want to convert this custom built in shader to custom URP shader

Shader "Custom/CoiledWire"
{
    Properties
    {
        _Color ("Color", Color) = (1,1,1,1)
        _MainTex ("Albedo (RGB)", 2D) = "white" {}
        _Glossiness ("Smoothness", Range(0,1)) = 0.5
        _Metallic ("Metallic", Range(0,1)) = 0.0
        _NumSpirals("Spirals", Range(0,50)) = 20
        _CableThickness("CableThickness", Range(0,50)) = 0.5
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 200
        Cull Off

        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;

        struct Input
        {
            float2 uv_MainTex;
        };

        half _Glossiness;
        half _Metallic;
        fixed4 _Color;
        float _NumSpirals;
        float _CableThickness;

        // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader.
        // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing.
        // #pragma instancing_options assumeuniformscaling
        UNITY_INSTANCING_BUFFER_START(Props)
            // put more per-instance properties here
        UNITY_INSTANCING_BUFFER_END(Props)

        float3 lerp3(float3 a, float3 b, float3 c, float t)
        {
            if (t <= 0.5f)
                return lerp(a, b, t / 0.5);
            else
                return lerp(b, c, (t - 0.5) / 0.5);
        }

        void surf (Input IN, inout SurfaceOutputStandard o)
        {
            // ported from https://medium.com/xrlo-extended-reality-lowdown/how-to-create-a-coiled-cable-shader-in-ue4-8bb47777d8ab

            // build coilded uvs
            float2 coiledUVs = IN.uv_MainTex;
            coiledUVs.x = frac(coiledUVs.x + coiledUVs.y * _NumSpirals);
      
            // normalize cable:
            float cable = saturate((coiledUVs.x / _CableThickness + 0.5) - (0.5 /_CableThickness));

            // buld normals:
            o.Normal = normalize(lerp3(float3(0,-1,0), float3(0,0,1), float3(0,1,0),cable));

            // build height map:
            float height = min(1 - cable, cable) * 2;

            // clip fragments outside the cable thickness:
            clip (height-0.01);

            // flat albedo color (could sample a texture here if desired)
            o.Albedo = _Color;

            // Metallic and smoothness come from slider variables
            o.Metallic = _Metallic;
            o.Smoothness = _Glossiness;
            o.Alpha = 1;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

So far I’ve done this

// This shader visuzlizes the normal vector values on the mesh.
Shader "Custom/CoiledWireURP"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
        _NumSpirals("Spirals", Range(0,50)) = 20
        _CableThickness("CableThickness", Range(0,50)) = 0.5
    }

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

        LOD 200
        Cull Off

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert        
            #pragma fragment frag
            #pragma target 3.0
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            CBUFFER_START(UnityPerMaterial)
                float _NumSpirals;
                float _CableThickness;
                half4 _Color;
            CBUFFER_END

            float2 coiledUVs;// = IN.attributes;

            struct Attributes
            {
                float4 positionOS   : POSITION;
                // Declaring the variable containing the normal vector for each
                // vertex.
                half3 normal        : NORMAL;
                float2 attributes   : TEXCOORD0;
            };

            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
                half3 normal        : TEXCOORD0;
            };

            float3 lerp3(float3 a, float3 b, float3 c, float t)
            {
                if (t <= 0.5f)
                    return lerp(a, b, t / 0.5);
                else
                    return lerp(b, c, (t - 0.5) / 0.5);
            }

            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                // Use the TransformObjectToWorldNormal function to transform the
                // normals from object to world space. This function is from the
                // SpaceTransforms.hlsl file, which is referenced in Core.hlsl.
                coiledUVs = IN.attributes;
                coiledUVs.x = frac(coiledUVs.x + coiledUVs.y * _NumSpirals);
        
                // // normalize cable:
                float cable = saturate((coiledUVs.x / _CableThickness + 0.5) - (0.5 /_CableThickness));

                OUT.normal = normalize(lerp3(float3(0,-1,0), float3(0,0,1), float3(0,1,0),cable));
            
                // float height = min(1 - cable, cable) * 2;

                // clip fragments outside the cable thickness:
                // clip (height-0.01);
            
                return OUT;
            }

            half4 frag(Varyings IN) : SV_Target
            {
                // half4 color = 0;
                // // IN.normal is a 3D vector. Each vector component has the range
                // // -1..1. To show all vector elements as color, including the
                // // negative values, compress each value into the range 0..1.
                // color.rgb = IN.normal * 0.5 + 0.5;
                // return color;
                half4 output = 0;

                coiledUVs = IN.normal;
                coiledUVs.x = frac(coiledUVs.x + coiledUVs.y * _NumSpirals);
        
                // // normalize cable:
                // float cable = saturate((coiledUVs.x / _CableThickness + 0.5) - (0.5 /_CableThickness));

                // // buld normals:
                // o.Normal = normalize(lerp3(float3(0,-1,0), float3(0,0,1), float3(0,1,0),cable));

                // // build height map:
                // float height = min(1 - cable, cable) * 2;
                output.rgb = float3(coiledUVs.x, coiledUVs.y, 0);

                return output;
            }

            //  half4 frag() : SV_Target
            // {          
            //     return _Color;
            // }
            ENDHLSL
        }
    }
}

I’m new to shader programming but I think I noticed that I need some clip function to work to achieve it. But it looks like I can’t use clip function in HLSL. What’s the equivalent function to this?
Any help will be appreciated. Thanks!

You should use clip inside fragment stage.

It will cause error. I’ve tried it

You only need past normal and position data from vertex to fragment stage.
For calculation of coiledUV should done inside fragment stage, then use clip.
I just modified you shader.Maybe you can take a look?

// This shader visuzlizes the normal vector values on the mesh.
Shader "Custom/CoiledWireURP"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
        _NumSpirals("Spirals", Range(0,50)) = 20
        _CableThickness("CableThickness", Range(0,50)) = 0.5
    }
   
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
       
        LOD 200
        Cull Off
       
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert       
            #pragma fragment frag
            #pragma target 3.0
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
           
            CBUFFER_START(UnityPerMaterial)
            float _NumSpirals;
            float _CableThickness;
            half4 _Color;
            CBUFFER_END

            sampler2D _MainTex;
           
            struct Attributes
            {
                float4 positionOS   : POSITION;
                // Declaring the variable containing the normal vector for each
                // vertex.
                half3 normal        : NORMAL;
            };
           
            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
                half3 normal        : TEXCOORD0;
            };
           
            float3 lerp3(float3 a, float3 b, float3 c, float t)
            {
                if (t <= 0.5f)
                return lerp(a, b, t / 0.5);
                else
                return lerp(b, c, (t - 0.5) / 0.5);
            }
           
            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                // Use the TransformObjectToWorldNormal function to transform the
                // normals from object to world space. This function is from the
                // SpaceTransforms.hlsl file, which is referenced in Core.hlsl.
                OUT.normal = TransformObjectToWorldNormal(IN.normal);
                return OUT;
            }
           
            half4 frag(Varyings IN) : SV_Target
            {
                // half4 color = 0;
                // // IN.normal is a 3D vector. Each vector component has the range
                // // -1..1. To show all vector elements as color, including the
                // // negative values, compress each value into the range 0..1.
                // color.rgb = IN.normal * 0.5 + 0.5;
                // return color;
                half4 output = 0;
               
                float2 coiledUVs = IN.normal;
                coiledUVs.x = frac(coiledUVs.x + coiledUVs.y * _NumSpirals);
               
                //normalize cable:
                float cable = saturate((coiledUVs.x / _CableThickness + 0.5) - (0.5 /_CableThickness));
               
                //buld normals:
                IN.normal = normalize(lerp3(float3(0,-1,0), float3(0,0,1), float3(0,1,0),cable));
               
                //build height map:
                float height = min(1 - cable, cable) * 2;

                // build height map:
                clip (height - 0.01f);

                output.rgb = float3(coiledUVs.x, coiledUVs.y, 0);
               
                return output;
            }
            ENDHLSL
        }
    }
}

6751303--778618--未命名-1.png

Hey sorry for the late reply.Yes I’ve checked it and it looks like it. Now the problem is how do we get the spiral like the one in my first shader script? Anyway thanks for taking your time to help me.
Maybe this will help you a bit

Calculate spiral uv from original uv instead of normal.
So you need pass uv coordinate form vertex to fragment stage.
Then calculate spiral uv like this.
Actually is what you did from first post.:slight_smile:

float2 coiledUVs = IN.uv;
//Number of spirals should be integer so spiral will be seamless.
coiledUVs = frac(coiledUVs.y * floor(_NumSpirals) + coiledUVs.x);

Entire code here.

// This shader visuzlizes the normal vector values on the mesh.
Shader "Custom/CoiledWireURP"
{
    Properties
    {
        _Color("Color", Color) = (1,1,1,1)
        _MainTex("Albedo (RGB)", 2D) = "white" {}
        _Glossiness("Smoothness", Range(0,1)) = 0.5
        _Metallic("Metallic", Range(0,1)) = 0.0
        _NumSpirals("Spirals", Range(0,50)) = 20
        _CableThickness("CableThickness", Range(0,50)) = 0.5
    }
   
    SubShader
    {
        Tags { "RenderType" = "Opaque" }
       
        LOD 200
        Cull Off
       
        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert     
            #pragma fragment frag
            #pragma target 3.0
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
           
            CBUFFER_START(UnityPerMaterial)
            float _NumSpirals;
            float _CableThickness;
            half4 _Color;
            CBUFFER_END
           
            sampler2D _MainTex;
           
            struct Attributes
            {
                float4 positionOS   : POSITION;
                // Declaring the variable containing the normal vector for each
                // vertex.
                half3 uv        : TEXCOORD0;
                half3 normal        : NORMAL;
            };
           
            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
                float2 uv        : TEXCOORD0;
                half3 normal        : TEXCOORD1;
            };
           
            Varyings vert(Attributes IN)
            {
                Varyings OUT;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                // Use the TransformObjectToWorldNormal function to transform the
                // normals from object to world space. This function is from the
                // SpaceTransforms.hlsl file, which is referenced in Core.hlsl.
                OUT.uv = IN.uv;
                OUT.normal = TransformObjectToWorldNormal(IN.normal);
                return OUT;
            }
           
            half4 frag(Varyings IN) : SV_Target
            {
                // half4 color = 0;
                // // IN.normal is a 3D vector. Each vector component has the range
                // // -1..1. To show all vector elements as color, including the
                // // negative values, compress each value into the range 0..1.
                // color.rgb = IN.normal * 0.5 + 0.5;
                // return color;
                half4 output = 0;
               
                float2 coiledUVs = IN.uv;
                coiledUVs = frac(coiledUVs.y * floor(_NumSpirals) + coiledUVs.x);

                output.rgb = float3(coiledUVs, 0);
               
                return output;
            }
            ENDHLSL
        }
    }
}