Modifying Wireframe Vertex Shader to Include Lighting & Shadows

Hello fellow developers!

I humbly seek the community’s assistance in combining two seemingly simple shaders into a single perfect shader.

Until a week ago, I was completely ignorant of the inner workings of shaders. Today, many hours of research later, I actually have a clue, but still fail to discover the solution for the puzzle that inspired it all.

I wish to create a wireframe vertex shader that only traces the edge of objects, but also receives lighting and casts shadows. I stumbled upon a shader that renders the wireframes almost perfectly, and another shader that that handles the lighting and shadows wonderfully.

As much as I strive, however, I fail to combine them.

Below is a composite image created from both individual shaders:

The above image perfectly illustrates the effect I hope to achieve.

The shader code used to create the wireframes are as follows:


Wireframe Shader

Shader "Custom/WireFrame"
{
    Properties
    {
	    _LineColor ("Line Color", Color) = (1,1,1,1)
	    _GridColor ("Grid Color", Color) = (1,1,1,0)
	    _LineWidth ("Line Width", float) = 0.2
    }
    
    SubShader
    {
        Tags { "RenderType" = "Transparent" }
	    Blend SrcAlpha OneMinusSrcAlpha
	    AlphaTest Greater 0.5
    
	    Pass
	    {
		    CGPROGRAM
		    #pragma vertex vert
		    #pragma fragment frag
		     
		    uniform float4 _LineColor;
		    uniform float4 _GridColor;
		    uniform float _LineWidth;
		     
		    // vertex input: position, uv1, uv2
		    struct appdata
		    {
			    float4 vertex : POSITION;
			    float4 texcoord1 : TEXCOORD0;
			    float4 color : COLOR;
		    };
		     
		    struct v2f
		    {
			    float4 pos : POSITION;
			    float4 texcoord1 : TEXCOORD0;
			    float4 color : COLOR;
		    };
		     
		    v2f vert (appdata v)
		    {
			    v2f o;
			    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
			    o.texcoord1 = v.texcoord1;
			    o.color = v.color;
			    return o;
		    }
		     
		    fixed4 frag(v2f i) : COLOR
		    {
			    fixed4 answer;
			     
			    float lx = step(_LineWidth, i.texcoord1.x);
			    float ly = step(_LineWidth, i.texcoord1.y);
			    float hx = step(i.texcoord1.x, 1.0 - _LineWidth);
			    float hy = step(i.texcoord1.y, 1.0 - _LineWidth);
			     
			    answer = lerp(_LineColor, _GridColor, lx*ly*hx*hy);
			     
			    return answer;
		    }
		    ENDCG
	    }
    }
Fallback "Vertex Colored", 1
}

And the shader that renders the shadows and lighting is below:


Shadow / Lighting Shader

Shader "Sample/Diffuse" 
{
	Properties 
	{
		_DiffuseTexture ("Diffuse Texture", 2D) = "white" {}
		_DiffuseTint ( "Diffuse Tint", Color) = (1, 1, 1, 1)
	}

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

		pass
		{		
			Tags { "LightMode"="ForwardBase"}

			CGPROGRAM

			#pragma target 3.0
			#pragma fragmentoption ARB_precision_hint_fastest

			#pragma vertex vertShadow
			#pragma fragment fragShadow
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"
			#include "AutoLight.cginc"

			sampler2D _DiffuseTexture;
			float4 _DiffuseTint;
			float4 _LightColor0;

			struct v2f
			{
				float4 pos : SV_POSITION;
				float3 lightDir : TEXCOORD0;
				float3 normal : TEXCOORD1;
				float2 uv : TEXCOORD2;
				LIGHTING_COORDS(3, 4)
			};

			v2f vertShadow(appdata_base v)
			{
				v2f o;

				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = v.texcoord;
				o.lightDir = normalize(ObjSpaceLightDir(v.vertex));
				o.normal = normalize(v.normal).xyz;

				TRANSFER_VERTEX_TO_FRAGMENT(o);

				return o; 
			}

			float4 fragShadow(v2f i) : COLOR
			{					
				float3 L = normalize(i.lightDir);
				float3 N = normalize(i.normal);	 

				float attenuation = LIGHT_ATTENUATION(i) * 2;
				float4 ambient = UNITY_LIGHTMODEL_AMBIENT * 2;

				float NdotL = saturate(dot(N, L));
				float4 diffuseTerm = NdotL * _LightColor0 * _DiffuseTint * attenuation;

				float4 diffuse = tex2D(_DiffuseTexture, i.uv);

				float4 finalColor = (ambient + diffuseTerm) * diffuse;

				return finalColor;
			}

			ENDCG
		}		

	} 
	FallBack "Diffuse"
}

I will be exceedingly grateful to those who help me to achieve or provide the shader code that I seek.

Thank you all in advance, and I hope you have a fantastic weekend!

Here is the combined shader that I created. It only contains a single lighting pass, which is all that I required. I hope that others find this shader useful as well!

Shader "Custom/Blueprint"
{
    Properties
    {
	    _LineColor ("Line Color", Color) = (1,1,1,1)
	    _GridColor ("Grid Color", Color) = (1,1,1,0)
	    _LineWidth ("Line Width", float) = 0.2
    }
    
    SubShader
    {
    	Tags { "RenderType" = "Opaque" }
    
	    Blend SrcAlpha OneMinusSrcAlpha
	    AlphaTest Greater 0.5
    
	    Pass
	    {
	    	Tags { "LightMode" = "ForwardBase" }
	    
		    CGPROGRAM
		    
		    #pragma target 3.0
		    #pragma fragmentoption ARB_precision_hint_fastest
		    
		    #pragma vertex vert
		    #pragma fragment frag
		    #pragma multi_compile_fwdbase
						
			#include "UnityCG.cginc"
			#include "AutoLight.cginc"
		     
		    float4 _LineColor;
		    float4 _GridColor;
		    float4 _LightColor0;
			float _LineWidth;
		     
		    struct v2f
		    {
			    float4 pos : POSITION;
			    float4 texcoord : TEXCOORD0;
				float3 normal : TEXCOORD1;
				float4 uv : TEXCOORD2;

			    LIGHTING_COORDS(3,4)
		    };
		     
		    v2f vert (appdata_base v)
		    {
			    v2f o;
			    o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
			    o.uv = v.texcoord;
				o.normal = normalize(v.normal).xyz;
			    o.texcoord = v.texcoord;

			    TRANSFER_VERTEX_TO_FRAGMENT(o);
			    
			    return o;
		    }
		     
		    fixed4 frag(v2f i) : COLOR
		    {
				float3 L = normalize( normalize( ObjSpaceLightDir(i.pos) ) );
				float3 N = normalize( i.normal );	
				
				float attenuation = LIGHT_ATTENUATION(i) * 2;
				float4 ambient = UNITY_LIGHTMODEL_AMBIENT * 4;
				
				float NdotL = saturate( dot(N, L) );
				float4 diffuseTerm = NdotL * _LightColor0 * attenuation;
			     
			    float lx = step(_LineWidth, i.texcoord.x);
			    float ly = step(_LineWidth, i.texcoord.y);
			    float hx = step(i.texcoord.x, 1.0 - _LineWidth);
			    float hy = step(i.texcoord.y, 1.0 - _LineWidth);

			    return lerp( _LineColor, _GridColor, lx*ly*hx*hy ) * ( ambient + diffuseTerm );

		    }
		    ENDCG
	    }
    }
Fallback "Diffuse"
}