# 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
}
Tags { "RenderType"="Opaque" }
LOD 200

CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types

// 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.
// #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

}
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.
// #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.