Is it possible to combine surface and vertex shaders?

Hello, I’m new to shaders but am trying to learn. Currently, I’m attempting to make an ocean shader. So far I’ve created a surface shader that scrolls a single normal map in three different directions, and have a vertex shader from Unity 5.x Shaders and Effects Cookbook that rolls a sine wave function across a plane. Here’s what they look like:

What I would like to do is combine them. Is this possible? Thanks in advance…

Also, here’s the shaders if interested:

Shader "Custom/SeaShader" {
	Properties {
		_Color ("Color", Color) = (1,1,1,1)
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_NormalTex("Normal Map 1", 2D) = "bump" {}
		_Glossiness ("Smoothness", Range(0,1)) = 0.5
		_Metallic ("Metallic", Range(0,1)) = 0.0

		_ScrollXSpeedN1 ("N1 X Scroll Speed", Range(-10, 10)) = -0.5
		_ScrollYSpeedN1 ("N1 Y Scroll Speed", Range(-10, 10)) = 0.5

		_ScrollXSpeedN2 ("N2 X Scroll Speed", Range(-10, 10)) = 0.5
		_ScrollYSpeedN2 ("N2 Y Scroll Speed", Range(-10, 10)) = 0.5

		_ScrollXSpeedN3 ("N3 X Scroll Speed", Range(-10, 10)) = 0
		_ScrollYSpeedN3 ("N3 Y Scroll Speed", Range(-10, 10)) = -0.5
	}
	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;

		struct Input {
			float2 uv_MainTex;
			float2 uv_NormalTex;
		};

		sampler2D _NormalTex;
		half _Glossiness;
		half _Metallic;
		fixed4 _Color;

		fixed _ScrollXSpeedN1;
		fixed _ScrollYSpeedN1;
		fixed _ScrollXSpeedN2;
		fixed _ScrollYSpeedN2;
		fixed _ScrollXSpeedN3;
		fixed _ScrollYSpeedN3;

		// 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_CBUFFER_START(Props)
			// put more per-instance properties here
		UNITY_INSTANCING_CBUFFER_END

		void surf (Input IN, inout SurfaceOutputStandard o) {
			
			//Create separate variables to store UVs
			//before passing to tex2D() function
			fixed2 scrolledUV1 = IN.uv_MainTex;
			fixed2 scrolledUV2 = IN.uv_MainTex;
			fixed2 scrolledUV3 = IN.uv_MainTex;

			//Create variables that store individual 
			//x and y components for the UV's scaled by time

			fixed n1XScrollValue = _ScrollXSpeedN1 * _Time;
			fixed n1YScrollValue = _ScrollYSpeedN1 * _Time;
			fixed n2XScrollValue = _ScrollXSpeedN2 * _Time;
			fixed n2YScrollValue = _ScrollYSpeedN2 * _Time;
			fixed n3XScrollValue = _ScrollXSpeedN3 * _Time;
			fixed n3YScrollValue = _ScrollYSpeedN3 * _Time;

			//Apply final UV offset
			scrolledUV1 += fixed2(n1XScrollValue, n1YScrollValue);
			scrolledUV2 += fixed2(n2XScrollValue, n2YScrollValue);
			scrolledUV3 += fixed2(n3XScrollValue, n3YScrollValue);
			
			//Apply textures and tint
			half4 c = tex2D(_MainTex, scrolledUV1) * _Color;
			
			// Albedo comes from a texture tinted by color
			o.Albedo = c.rgb;
			// Metallic and smoothness come from slider variables
			o.Metallic = _Metallic;
			o.Smoothness = _Glossiness;
			o.Alpha = c.a;

			float3 normalMap = UnpackNormal(tex2D(_NormalTex, scrolledUV1) + (tex2D(_NormalTex, scrolledUV2)*2-1)) + (tex2D(_NormalTex, scrolledUV3)*2-1);
			o.Normal = normalMap.rgb;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

Shader "Custom/WaveShader" {
	Properties {
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_Color ("Color", Color) = (1,1,1,1)
		_tintAmount ("Tint Amount", Range(0, 1)) = 0.5
		_ColorA ("Color A", Color) = (1,1,1,1)
		_ColorB ("Color B", Color) = (1,1,1,1)		
		_Speed ("Wave Speed", Range(0.1, 80)) = 5
		_Frequency ("Wave Frequency", Range(0, 5)) = 2
		_Amplitude ("Wave Amplitude", Range(-1, 1)) = 1

	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		// Physically based Standard lighting model, and enable shadows on all light types
		#pragma surface surf Lambert vertex:vert

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

		sampler2D _MainTex;
		float4 _ColorA;
		float4 _ColorB;
		float _tintAmount;
		float _Speed;
		float _Frequency;
		float _Amplitude;
		//float _OffsetVal;
		fixed4 _Color;

		struct Input {
			float2 uv_MainTex;
			float3 vertColor;
		};

		void vert(inout appdata_full v, out Input o)
		{
			UNITY_INITIALIZE_OUTPUT(Input,o);
			float time = _Time * _Speed;
			float waveValueA = sin(time + v.vertex.x * _Frequency) * _Amplitude;

			v.vertex.xyz = float3(v.vertex.x, v.vertex.y + waveValueA, v.vertex.z);
			v.normal = normalize(float3(v.normal.x + waveValueA, v.normal.y, v.normal.z));
			o.vertColor = float3(waveValueA, waveValueA, waveValueA);
		}		

		// 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_CBUFFER_START(Props)
			// put more per-instance properties here
		UNITY_INSTANCING_CBUFFER_END

		void surf (Input IN, inout SurfaceOutput o) 
		{
			half4 c = tex2D(_MainTex, IN.uv_MainTex);
			float3 tintColor = lerp(_ColorA, _ColorB, IN.vertColor).rgb;

			// Albedo comes from a texture tinted by color
			//fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
			o.Albedo = c.rgb * (tintColor * _tintAmount);
			//o.Albedo = c.rgb;

			// Metallic and smoothness come from slider variables
			o.Alpha = c.a;
		}
		ENDCG
	}
	FallBack "Diffuse"
}

You can, and that’s exactly what is done in the exemples : look at “Normal Extrusion with Vertex Modifier” of Unity - Manual: Surface Shader examples .

Also, if you take a look at your “Custom/WaveShader”, you’ll notice it’s already a surface shader :-). The #pragma surf is here to declare a surface shader ; Lamber is the lighting model ; vertex:vert declares the vertex function, and that’s what you are looking for.

You can also search for “vertex:vert” in the same exmaple link-

If you need the lighting to work (the benefit of using surface shader), then it gets trickier. Surface shaders transform into clip/screen space behind the scene, after the execution of your main vertex shader method. Since billboard transformation needs to break down that transformation things get messy: you need to transform the vertices into their final clip space position, and then convert it back into object space so it can be re-transformed again behind the scene into the desired position. Vertex shaders could be define as the shader programs that modifies the geometry of the scene and made the 3D projection.