Combine Two Shaders Into One - Help

Ok, so I own shaderforge, because I’m pretty crappy at writing my own shaders, I have a basic Emissive Shader that can also receive Shadows that I developed. I also have a seperate Curved Horizon shader that I modified to my own needs from the web.

I would like to combine the curved shader into my emissive shader, but each time I’ve tried, I’ve clearly not understood how both shaders relate to each other and how I can merge the curved shader in with shaderforge shader, and so, final result, a complete mess that does not work, I’m hoping someone could take a look at both shaders, and possibly help ?

The curved shader :

Shader "playmint/curved/curved"
{
    Properties
    {
        _Color ("Main Colour", Color) = (1,1,1,1)
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }

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

        CGPROGRAM
        #pragma surface surf Lambert vertex:vert addshadow

        // Global Shader values
        uniform float2 _BendAmount;
        uniform float3 _BendOrigin;
        uniform float _BendFalloff;

        sampler2D _MainTex;
        fixed4 _Color;

        struct Input
        {
              float2 uv_MainTex;
        };

        float4 Curve(float4 v)
        {
              //HACK: Considerably reduce amount of Bend
              _BendAmount *= .0001;

              float4 world = mul(unity_ObjectToWorld, v);

              float dist = length(world.xz-_BendOrigin.xz);

              dist = max(0, dist-_BendFalloff);

              // Distance squared
              dist = dist*dist;

              world.xy += dist*_BendAmount;
              return mul(unity_WorldToObject, world);
        }

        void vert(inout appdata_full v)
        {
              v.vertex = Curve(v.vertex);
        }

        void surf(Input IN, inout SurfaceOutput o)
        {
              fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
              o.Albedo = c.rgb;
              o.Alpha = c.a;
        }

        ENDCG
    }
      Fallback "Mobile/Diffuse"
}

and, my Emissive shader :

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// Shader created with Shader Forge v1.36
// Shader Forge (c) Neat Corporation / Joachim Holmer - http://www.acegikmo.com/shaderforge/
// Note: Manually altering this data may prevent you from opening it in Shader Forge
/*SF_DATA;ver:1.36;sub:START;pass:START;ps:flbk:,iptp:0,cusa:False,bamd:0,cgin:,lico:1,lgpr:1,limd:1,spmd:1,trmd:0,grmd:0,uamb:True,mssp:True,bkdf:False,hqlp:False,rprd:False,enco:False,rmgx:True,imps:True,rpth:0,vtps:0,hqsc:True,nrmq:1,nrsp:0,vomd:0,spxs:False,tesm:0,olmd:1,culm:0,bsrc:0,bdst:1,dpts:2,wrdp:True,dith:0,atcv:False,rfrpo:True,rfrpn:Refraction,coma:15,ufog:True,aust:True,igpj:False,qofs:0,qpre:1,rntp:1,fgom:False,fgoc:False,fgod:False,fgor:False,fgmd:0,fgcr:0.5,fgcg:0.5,fgcb:0.5,fgca:1,fgde:0.01,fgrn:0,fgrf:300,stcl:False,stva:128,stmr:255,stmw:255,stcp:6,stps:0,stfa:0,stfz:0,ofsf:0,ofsu:0,f2p0:False,fnsp:False,fnfb:False,fsmp:False;n:type:ShaderForge.SFN_Final,id:4013,x:32719,y:32712,varname:node_4013,prsc:2|emission-2128-OUT;n:type:ShaderForge.SFN_Tex2d,id:3122,x:32333,y:32486,ptovrint:False,ptlb:smile:iffuse Texture,ptin:_DiffuseTexture,varname:node_3122,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,ntxv:0,isnm:False;n:type:ShaderForge.SFN_Multiply,id:2128,x:32537,y:32670,varname:node_2128,prsc:2|A-3122-RGB,B-5967-OUT;n:type:ShaderForge.SFN_LightAttenuation,id:5967,x:32333,y:32670,varname:node_5967,prsc:2;proporder:3122;pass:END;sub:END;*/

Shader "playmint/emissive/Em + Shade" {
    Properties {
        _DiffuseTexture ("Diffuse Texture", 2D) = "white" {}
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
           
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0
            uniform sampler2D _DiffuseTexture; uniform float4 _DiffuseTexture_ST;
            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                LIGHTING_COORDS(1,2)
                UNITY_FOG_COORDS(3)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
                float3 attenColor = attenuation * _LightColor0.xyz;
////// Emissive:
                float4 _DiffuseTexture_var = tex2D(_DiffuseTexture,TRANSFORM_TEX(i.uv0, _DiffuseTexture));
                float3 emissive = (_DiffuseTexture_var.rgb*attenuation);
                float3 finalColor = emissive;
                fixed4 finalRGBA = fixed4(finalColor,1);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
        Pass {
            Name "FORWARD_DELTA"
            Tags {
                "LightMode"="ForwardAdd"
            }
            Blend One One
           
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDADD
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdadd_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0
            uniform sampler2D _DiffuseTexture; uniform float4 _DiffuseTexture_ST;
            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                LIGHTING_COORDS(1,2)
                UNITY_FOG_COORDS(3)
            };
            VertexOutput vert (VertexInput v) {
                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
                float3 attenColor = attenuation * _LightColor0.xyz;
                float3 finalColor = 0;
                fixed4 finalRGBA = fixed4(finalColor * 1,0);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
    CustomEditor "ShaderForgeMaterialInspector"
}

That should be very simple.

  1. put these variable declarations for _BendAmount, _BendOrigin, _BendFalloff into the passes of the second shader.
  2. put the Curve function into nto the passes of the second shader.
  3. put this statement: “v.vertex = Curve(v.vertex);” at the beginning of the vert function in both passes of the second shader.
  4. Use second shader modified that way as the combined shader.
1 Like

Thanks, I still haven’t got it working yet, but I feel like I’m on the right track a bit more now.

I ‘think’ I’ve acted upon your advice, but the shader does not work at all, literally just get an invisible object in my scene that the shader is applied to. Maybe I’ve put something in the wrong section ?

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

// Shader created with Shader Forge v1.36
// Shader Forge (c) Neat Corporation / Joachim Holmer - http://www.acegikmo.com/shaderforge/
// Note: Manually altering this data may prevent you from opening it in Shader Forge
/*SF_DATA;ver:1.36;sub:START;pass:START;ps:flbk:,iptp:0,cusa:False,bamd:0,cgin:,lico:1,lgpr:1,limd:1,spmd:1,trmd:0,grmd:0,uamb:True,mssp:True,bkdf:False,hqlp:False,rprd:False,enco:False,rmgx:True,imps:True,rpth:0,vtps:0,hqsc:True,nrmq:1,nrsp:0,vomd:0,spxs:False,tesm:0,olmd:1,culm:0,bsrc:0,bdst:1,dpts:2,wrdp:True,dith:0,atcv:False,rfrpo:True,rfrpn:Refraction,coma:15,ufog:True,aust:True,igpj:False,qofs:0,qpre:1,rntp:1,fgom:False,fgoc:False,fgod:False,fgor:False,fgmd:0,fgcr:0.5,fgcg:0.5,fgcb:0.5,fgca:1,fgde:0.01,fgrn:0,fgrf:300,stcl:False,stva:128,stmr:255,stmw:255,stcp:6,stps:0,stfa:0,stfz:0,ofsf:0,ofsu:0,f2p0:False,fnsp:False,fnfb:False,fsmp:False;n:type:ShaderForge.SFN_Final,id:4013,x:32719,y:32712,varname:node_4013,prsc:2|emission-2128-OUT;n:type:ShaderForge.SFN_Tex2d,id:3122,x:32333,y:32486,ptovrint:False,ptlb:smile:iffuse Texture,ptin:_DiffuseTexture,varname:node_3122,prsc:2,glob:False,taghide:False,taghdr:False,tagprd:False,tagnsco:False,tagnrm:False,ntxv:0,isnm:False;n:type:ShaderForge.SFN_Multiply,id:2128,x:32537,y:32670,varname:node_2128,prsc:2|A-3122-RGB,B-5967-OUT;n:type:ShaderForge.SFN_LightAttenuation,id:5967,x:32333,y:32670,varname:node_5967,prsc:2;proporder:3122;pass:END;sub:END;*/

Shader "playmint/curved/Curve + Em + Shade" {
    Properties {
        _DiffuseTexture ("Diffuse Texture", 2D) = "white" {}
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0

            uniform float _BendFalloff;
            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;

            uniform sampler2D _DiffuseTexture; uniform float4 _DiffuseTexture_ST;

            float Curve(float4 v)
            {
            // Hack : Considerably reduce amount of Bend
            _BendAmount *= .0001;
            float4 world = mul(unity_ObjectToWorld, v);
            float dist = length(world.xz-_BendOrigin.xz);
            dist = max(0, dist-_BendFalloff);
            dist = dist*dist;
            world.xy += dist*_BendAmount;
            return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };

            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                LIGHTING_COORDS(1,2)
                UNITY_FOG_COORDS(3)
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
                float3 attenColor = attenuation * _LightColor0.xyz;
////// Emissive:
                float4 _DiffuseTexture_var = tex2D(_DiffuseTexture,TRANSFORM_TEX(i.uv0, _DiffuseTexture));
                float3 emissive = (_DiffuseTexture_var.rgb*attenuation);
                float3 finalColor = emissive;
                fixed4 finalRGBA = fixed4(finalColor,1);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }

            ENDCG
        }
        Pass {
            Name "FORWARD_DELTA"
            Tags {
                "LightMode"="ForwardAdd"
            }
            Blend One One
           
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDADD
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdadd_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 3.0

               uniform float _BendFalloff;
            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;

            uniform sampler2D _DiffuseTexture; uniform float4 _DiffuseTexture_ST;

            float Curve(float4 v)
            {
            // Hack : Considerably reduce amount of Bend
            _BendAmount *= .0001;
            float4 world = mul(unity_ObjectToWorld, v);
            float dist = length(world.xz-_BendOrigin.xz);
            dist = max(0, dist-_BendFalloff);
            dist = dist*dist;
            world.xy += dist*_BendAmount;
            return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };

            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                LIGHTING_COORDS(1,2)
                UNITY_FOG_COORDS(3)
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
                float3 attenColor = attenuation * _LightColor0.xyz;
                float3 finalColor = 0;
                fixed4 finalRGBA = fixed4(finalColor * 1,0);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
    CustomEditor "ShaderForgeMaterialInspector"
}

If I remove the v.vertex = Curve(v.vertex); line, then my shader becomes visible again, minus any curve abilities, only the emissive and shadows part of the shader then work.

Anybody can offer any insight on this, as to what I may be doing wrong ?

Maybe a real expert could tell what is wrong almost straightaway from the code - but I would try adding the emissive shader features one by one to the curved shader.

Well, through lots of experimentation and hair pulling, finally managed to figure it out ! :slight_smile:

Shadows are not right when curvature takes place, but I think I can figure that out, I’ll post a fixed version as soon as I finish it.

Code below :

Shader "playmint/curved/Curve + Unlit + Shade" {
    Properties {
        _BaseRGB ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags {
            "RenderType"="Opaque"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
           
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            // Global Shader Values

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGB; uniform float4 _BaseRGB_ST;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;

                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);

                  // Distance squared
                  dist = dist*dist;

                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                LIGHTING_COORDS(1,2)
                UNITY_FOG_COORDS(3)
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
////// Emissive:
                float4 _BaseRGB_var = tex2D(_BaseRGB,TRANSFORM_TEX(i.uv0, _BaseRGB));
                float3 emissive = (_BaseRGB_var.rgb*attenuation);
                float3 finalColor = emissive;
                fixed4 finalRGBA = fixed4(finalColor,1);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}
2 Likes

Well, that all took some figuring out, NEW version of my unlit curved shader, support textures with transparency and shadows correctly now, single sided version :

Shader "playmint/curve unlit/CurveUnlit + Shade + Alpha" {
    Properties {
        _BaseRGBTransA ("Base (RGB) Trans (A)", 2D) = "white" {}
        [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader {
        Tags {
            "IgnoreProjector"="True"
            "Queue"="Transparent"
            "RenderType"="Transparent"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
         
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGBTransA; uniform float4 _BaseRGBTransA_ST;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;
                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);
                  // Distance squared
                  dist = dist*dist;
                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
                float4 _BaseRGBTransA_var = tex2D(_BaseRGBTransA,TRANSFORM_TEX(i.uv0, _BaseRGBTransA));
                clip(_BaseRGBTransA_var.a - 0.5);
////// Lighting:
                float attenuation = 1;
////// Emissive:
                float3 emissive = (_BaseRGBTransA_var.rgb*attenuation);
                float3 finalColor = emissive;
                return fixed4(finalColor,_BaseRGBTransA_var.a);
            }
            ENDCG
        }
        Pass {
            Name "ShadowCaster"
            Tags {
                "LightMode"="ShadowCaster"
            }
            Offset 1, 1
            Cull Back
         
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_SHADOWCASTER
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma multi_compile_shadowcaster
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGBTransA; uniform float4 _BaseRGBTransA_ST;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;
                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);
                  // Distance squared
                  dist = dist*dist;
                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                V2F_SHADOW_CASTER;
                float2 uv0 : TEXCOORD1;
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                TRANSFER_SHADOW_CASTER(o)
                return o;
            }
            float4 frag(VertexOutput i) : COLOR {
                float4 _BaseRGBTransA_var = tex2D(_BaseRGBTransA,TRANSFORM_TEX(i.uv0, _BaseRGBTransA));
                clip(_BaseRGBTransA_var.a - 0.5);
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

And, a version that supports double sided :

Shader "playmint/curve unlit/CurveUnlit + Shade + AlphaDs" {
    Properties {
        _BaseRGBTransA ("Base (RGB) Trans (A)", 2D) = "white" {}
        [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader {
        Tags {
            "IgnoreProjector"="True"
            "Queue"="Transparent"
            "RenderType"="Transparent"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off
            ZWrite Off
         
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGBTransA; uniform float4 _BaseRGBTransA_ST;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;
                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);
                  // Distance squared
                  dist = dist*dist;
                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                return o;
            }
            float4 frag(VertexOutput i, float facing : VFACE) : COLOR {
                float isFrontFace = ( facing >= 0 ? 1 : 0 );
                float faceSign = ( facing >= 0 ? 1 : -1 );
                float4 _BaseRGBTransA_var = tex2D(_BaseRGBTransA,TRANSFORM_TEX(i.uv0, _BaseRGBTransA));
                clip(_BaseRGBTransA_var.a - 0.5);
////// Lighting:
                float attenuation = 1;
////// Emissive:
                float3 emissive = (_BaseRGBTransA_var.rgb*attenuation);
                float3 finalColor = emissive;
                return fixed4(finalColor,_BaseRGBTransA_var.a);
            }
            ENDCG
        }
        Pass {
            Name "ShadowCaster"
            Tags {
                "LightMode"="ShadowCaster"
            }
            Offset 1, 1
            Cull Off
         
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_SHADOWCASTER
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma multi_compile_shadowcaster
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGBTransA; uniform float4 _BaseRGBTransA_ST;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;
                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);
                  // Distance squared
                  dist = dist*dist;
                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                V2F_SHADOW_CASTER;
                float2 uv0 : TEXCOORD1;
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                TRANSFER_SHADOW_CASTER(o)
                return o;
            }
            float4 frag(VertexOutput i, float facing : VFACE) : COLOR {
                float isFrontFace = ( facing >= 0 ? 1 : 0 );
                float faceSign = ( facing >= 0 ? 1 : -1 );
                float4 _BaseRGBTransA_var = tex2D(_BaseRGBTransA,TRANSFORM_TEX(i.uv0, _BaseRGBTransA));
                clip(_BaseRGBTransA_var.a - 0.5);
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

And, lastly, same but with Alpha Cutoff enabled ( Double Sided ) :

Shader "playmint/curve unlit/CurveUnlit + Shade + AlphaCutDs" {
    Properties {
        _BaseRGB ("Base (RGB)", 2D) = "white" {}
        _Cutoff ("Cutoff", Range(0, 1)) = 0.5
        [HideInInspector]_Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
    }
    SubShader {
        Tags {
            "Queue"="AlphaTest"
            "RenderType"="TransparentCutout"
        }
        Pass {
            Name "FORWARD"
            Tags {
                "LightMode"="ForwardBase"
            }
            Cull Off
          
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_FORWARDBASE
            #include "UnityCG.cginc"
            #include "AutoLight.cginc"
            #include "Lighting.cginc"
            #pragma multi_compile_fwdbase_fullshadows
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGB; uniform float4 _BaseRGB_ST;
            uniform float _Cutoff;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;
                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);
                  // Distance squared
                  dist = dist*dist;
                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                float4 pos : SV_POSITION;
                float2 uv0 : TEXCOORD0;
                LIGHTING_COORDS(1,2)
                UNITY_FOG_COORDS(3)
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                UNITY_TRANSFER_FOG(o,o.pos);
                TRANSFER_VERTEX_TO_FRAGMENT(o)
                return o;
            }
            float4 frag(VertexOutput i, float facing : VFACE) : COLOR {
                float isFrontFace = ( facing >= 0 ? 1 : 0 );
                float faceSign = ( facing >= 0 ? 1 : -1 );
                float4 _BaseRGB_var = tex2D(_BaseRGB,TRANSFORM_TEX(i.uv0, _BaseRGB));
                clip(((_BaseRGB_var.a+_Cutoff)*_Cutoff) - 0.5);
////// Lighting:
                float attenuation = LIGHT_ATTENUATION(i);
////// Emissive:
                float3 emissive = (_BaseRGB_var.rgb*attenuation);
                float3 finalColor = emissive;
                fixed4 finalRGBA = fixed4(finalColor,1);
                UNITY_APPLY_FOG(i.fogCoord, finalRGBA);
                return finalRGBA;
            }
            ENDCG
        }
        Pass {
            Name "ShadowCaster"
            Tags {
                "LightMode"="ShadowCaster"
            }
            Offset 1, 1
            Cull Off
          
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #define UNITY_PASS_SHADOWCASTER
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #pragma fragmentoption ARB_precision_hint_fastest
            #pragma multi_compile_shadowcaster
            #pragma multi_compile_fog
            #pragma only_renderers d3d9 d3d11 glcore gles
            #pragma target 2.0

            uniform float2 _BendAmount;
            uniform float3 _BendOrigin;
            uniform float _BendFalloff;

            uniform sampler2D _BaseRGB; uniform float4 _BaseRGB_ST;
            uniform float _Cutoff;

            float4 Curve(float4 v)
            {
                // Hack : Considerably reduce amount of Bend
                  _BendAmount *= .0001;
                  float4 world = mul(unity_ObjectToWorld, v);
                  float dist = length(world.xz-_BendOrigin.xz);
                  dist = max(0, dist-_BendFalloff);
                  // Distance squared
                  dist = dist*dist;
                  world.xy += dist*_BendAmount;
                  return mul(unity_WorldToObject, world);
            }

            struct VertexInput {
                float4 vertex : POSITION;
                float2 texcoord0 : TEXCOORD0;
            };
            struct VertexOutput {
                V2F_SHADOW_CASTER;
                float2 uv0 : TEXCOORD1;
            };
            VertexOutput vert (VertexInput v) {

                v.vertex = Curve(v.vertex);

                VertexOutput o = (VertexOutput)0;
                o.uv0 = v.texcoord0;
                o.pos = UnityObjectToClipPos(v.vertex );
                TRANSFER_SHADOW_CASTER(o)
                return o;
            }
            float4 frag(VertexOutput i, float facing : VFACE) : COLOR {
                float isFrontFace = ( facing >= 0 ? 1 : 0 );
                float faceSign = ( facing >= 0 ? 1 : -1 );
                float4 _BaseRGB_var = tex2D(_BaseRGB,TRANSFORM_TEX(i.uv0, _BaseRGB));
                clip(((_BaseRGB_var.a+_Cutoff)*_Cutoff) - 0.5);
                SHADOW_CASTER_FRAGMENT(i)
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

would seem a bit remiss if I didn’t post the control script :

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class curveController : MonoBehaviour
{
    private float currentCurvatureX;
    private float newCurvatureX;
    private float currentCurvatureY;
    private float newCurvatureY;

    [Header("Time Before Curvature Begins")]
    public float timeToWait = 30f;

    [Header("Time Between Curvature Changes")]
    public float timeInterval = 30f;

    [Header("Curve Origin - Main Camera")]
    public Transform CurveOrigin;

    [Header("Curvature")]

    [Range(-500f, 500f)]
    [SerializeField]
    float curvatureX = 0f;

    [Range(-500f, 500f)]
    [SerializeField]
    float curvatureY = 0f;

    [Range(0f, 50f)]
    [SerializeField]
    [Header("Falloff Effect")]
    float falloff = 0f;

    private Vector2 bendAmount = Vector2.zero;

    // Global shader property ids
    private int bendAmountId;
    private int bendOriginId;
    private int bendFalloffId;

    void Start ()
    {
        bendAmountId = Shader.PropertyToID("_BendAmount");
        bendOriginId = Shader.PropertyToID("_BendOrigin");
        bendFalloffId = Shader.PropertyToID("_BendFalloff");

        // Make sure we start with default X and Y curvature
        curvatureX = 0f;
        curvatureY = 0f;

        StartCoroutine(InitiateCoroutinesInOrder());
    }

    void Update ()
    {
        bendAmount.x=curvatureX;
        bendAmount.y=curvatureY;

        Shader.SetGlobalVector(bendAmountId, bendAmount);
        Shader.SetGlobalVector(bendOriginId, CurveOrigin.position);
        Shader.SetGlobalFloat(bendFalloffId, falloff);
    }

    IEnumerator InitiateCoroutinesInOrder () {

        yield return StartCoroutine(waitUntilStart());
        yield return StartCoroutine(changePathCurvature());
    }

    IEnumerator waitUntilStart() {

        yield return new WaitForSeconds(timeToWait);
    }

    IEnumerator changePathCurvature() {
        // Keep repeating
        while(true) {
         
            // currentCurvatureX - Get current value of CurvatureX
            float currentCurvatureX = curvatureX;
            // newCurvatureX = Random within a range of -50 and 50
            float newCurvatureX = (Random.Range(-50.0f, 50.0f));

            // currentCurvatureY - Get current value of CurvatureY
            float currentCurvatureY = curvatureY;
            // newCurvatureY = Random within a range of -50 and 50
            float newCurvatureY = (Random.Range(-50.0f, 50.0f));

            // t = reference to Time
            float t = 0;

            // t = 0, if t is less than or equal to timeInterval, then increase t until we reach TimeInterval

            for(t = 0; t <= timeInterval; t+=Time.deltaTime) {
                curvatureX = Mathf.Lerp(currentCurvatureX, newCurvatureX, t / timeInterval);
                curvatureY = Mathf.Lerp(currentCurvatureY, newCurvatureY, t / timeInterval);
                yield return null;
            }
        }
    }
}
1 Like

Hey man! Can you help me with mixing 2 my shaders, curved and low poly water?