How to convert any/this example shader of surface to vertex and fragment method?

How to convert any/this example shader of surface to vertex and fragment method?

A example code:

Shader "Nature/Terrain/Bumped Specular" {
Properties {
	_SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 1)
	_Shininess ("Shininess", Range (0.03, 1)) = 0.078125

	// set by terrain engine
	[HideInInspector] _Control ("Control (RGBA)", 2D) = "red" {}
	[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
	[HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
	[HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
	[HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
	[HideInInspector] _Normal3 ("Normal 3 (A)", 2D) = "bump" {}
	[HideInInspector] _Normal2 ("Normal 2 (B)", 2D) = "bump" {}
	[HideInInspector] _Normal1 ("Normal 1 (G)", 2D) = "bump" {}
	[HideInInspector] _Normal0 ("Normal 0 (R)", 2D) = "bump" {}
	// used in fallback on old cards  base map
	[HideInInspector] _MainTex ("BaseMap (RGB)", 2D) = "white" {}
	[HideInInspector] _Color ("Main Color", Color) = (1,1,1,1)
}
	
SubShader {
	Tags {
		"SplatCount" = "4"
		"Queue" = "Geometry-100"
		"RenderType" = "Opaque"
	}
CGPROGRAM
#pragma surface surf BlinnPhong vertex:vert
#pragma target 3.0

void vert (inout appdata_full v)
{
	v.tangent.xyz = cross(v.normal, float3(0,0,1));
	v.tangent.w = -1;
}

struct Input {
	float2 uv_Control : TEXCOORD0;
	float2 uv_Splat0 : TEXCOORD1;
	float2 uv_Splat1 : TEXCOORD2;
	float2 uv_Splat2 : TEXCOORD3;
	float2 uv_Splat3 : TEXCOORD4;
};

sampler2D _Control;
sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
sampler2D _Normal0,_Normal1,_Normal2,_Normal3;
half _Shininess;

void surf (Input IN, inout SurfaceOutput o) {
	fixed4 splat_control = tex2D (_Control, IN.uv_Control);
	fixed4 col;
	col  = splat_control.r * tex2D (_Splat0, IN.uv_Splat0);
	col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1);
	col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2);
	col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3);
	o.Albedo = col.rgb;

	fixed4 nrm;
	nrm  = splat_control.r * tex2D (_Normal0, IN.uv_Splat0);
	nrm += splat_control.g * tex2D (_Normal1, IN.uv_Splat1);
	nrm += splat_control.b * tex2D (_Normal2, IN.uv_Splat2);
	nrm += splat_control.a * tex2D (_Normal3, IN.uv_Splat3);
	// Sum of our four splat weights might not sum up to 1, in
	// case of more than 4 total splat maps. Need to lerp towards
	// "flat normal" in that case.
	fixed splatSum = dot(splat_control, fixed4(1,1,1,1));
	fixed4 flatNormal = fixed4(0.5,0.5,1,0.5); // this is "flat normal" in both DXT5nm and xyz*2-1 cases
	nrm = lerp(flatNormal, nrm, splatSum);
	o.Normal = UnpackNormal(nrm);

	o.Gloss = col.a * splatSum;
	o.Specular = _Shininess;

	o.Alpha = 0.0;
}
ENDCG  
}

Dependency "AddPassShader" = "Hidden/Nature/Terrain/Bumped Specular AddPass"
Dependency "BaseMapShader" = "Specular"

Fallback "Nature/Terrain/Diffuse"
}

By performing the lighting calculations in the vertex or fragment shader.

The question is about a rather large topic, so I decided to limit my answer to the core question: “What is the difference between Surface shaders and regular Vertex and Fragment shaders?”
Answer: Surface Shaders handle lighting for you.

You can find more information in the documentation on Surface Shaders and Vertex/Fragment Shaders and on Aras’s Blog

and to take this advice further, by looking through all the CGIncludes from the built-in shader source, tracking how it integrates into the shader source you’ve posted and by adding ‘pragma debug’ to the shader then looking at the compiled shader source (in Unity select the shader, then click ‘open compiled source’ in the inspector.

@RC-1290 and @noisecrime, thanks for replying!

I need to convert the shaders to use a Tasharen Fog of War, in mobile. The code was done by a guy named @shiva.js in forum.

I’ll put here your explanation:

I made it for something as diffuse and shaders that already has vertex and fragment shader

Any idea to put this in surface shader?

I’m having some difficulty understanding your post and what you want. If you get the impression I misunderstood you, you could try to ask someone to help you translate the post from your native language to English.


If you want to apply the changes suggested by shiva.js, you can do that without converting from surface to vertex+fragment shader. You can indicate that a function should be called at the start of the vertex shader (called vertex modification function in the documentation), by adding “vertex: functionName” to the #pragma that mentions the surface shader
For example:

#pragma surface surf BlinnPhong vertex:someVertexFunction

There’s an example in the Built-in Tree Bark shader.

If this is confusing, I recommend taking time to learn Cg and shader programming in Unity. If you want someone else to do the work for you, you can wait and hope someone is kind enough to put the time and effort in, or hire someone.

Sorry for my bad english :confused: I understand the reading of English, but I’m not good at applying…
I’ll try to be more specific with my situation:


I downloaded the “Unity Built-in Shaders” to take a look, and applied the code sent by @shiva.js.
I attached the code to each object on the scene, but the terrain uses “Nature/Terrain/Diffuse” shader and I need adapt code for this shader…
I made some changes in the code, and now I have this:

Shader "Mobile/Fog of War/Nature/Terrain/Diffuse" {
Properties {
	[HideInInspector] _Control ("Control (RGBA)", 2D) = "red" {}
	[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
	[HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
	[HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
	[HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
	// used in fallback on old cards  base map
	[HideInInspector] _MainTex ("BaseMap (RGB)", 2D) = "white" {}
	[HideInInspector] _Color ("Main Color", Color) = (1,1,1,1)
}
	
SubShader {
	Tags {
		"SplatCount" = "4"
		"Queue" = "Geometry-100"
		"RenderType" = "Opaque"
	}
	Pass
	{
		CGPROGRAM
//		#pragma surface surf Lambert
		
		struct Input {
			float2 uv_Control : TEXCOORD0;
			float2 uv_Splat0 : TEXCOORD1;
			float2 uv_Splat1 : TEXCOORD2;
			float2 uv_Splat2 : TEXCOORD3;
			float2 uv_Splat3 : TEXCOORD4;
		};
		
		sampler2D _Control;
		sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
		
		void surf (Input IN, inout SurfaceOutput o) {
			fixed4 splat_control = tex2D (_Control, IN.uv_Control);
			fixed3 col;
			col  = splat_control.r * tex2D (_Splat0, IN.uv_Splat0).rgb;
			col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1).rgb;
			col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2).rgb;
			col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3).rgb;
			o.Albedo = col;
			o.Alpha = 0.0;
		}
		ENDCG
	}
	
	Pass
	{
		CGPROGRAM
		#pragma vertex vert_surf
		#pragma fragment frag_surf
		
		#include "UnityCG.cginc"
	
		struct v2f_surf {
		    float4  pos : SV_POSITION;
		    float2  uv : TEXCOORD0;
		   
		    float2 fog : TEXCOORD2;
		};
		
		float4 _Color;
		sampler2D _MainTex;
		
		//begin regin FOG_OF_WAR
		sampler2D _FogTex0;
		sampler2D _FogTex1;
		uniform float4 _Params;
		uniform half4 _Unexplored;
		uniform half4 _Explored;
		//end regin
		
		float4 _MainTex_ST;
		
		v2f_surf vert_surf (appdata_full v) {
			v2f_surf o;
		  
		    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
		    o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
		   
		    float4 worldPos = mul (_Object2World, v.vertex);
		    o.fog.xy = worldPos.xz * _Params.z + _Params.xy;
		  
			return o;
		}
		
		half4 frag_surf (v2f_surf IN) : COLOR
		{
			half4 c = tex2D (_MainTex, IN.uv);
			
			half4 fog = lerp(tex2D(_FogTex0, IN.fog), tex2D(_FogTex1, IN.fog), _Params.w);
			c= lerp(lerp(c * _Unexplored, c * _Explored, fog.g), c, fog.r);
		  
			return c * _Color;
		}
		ENDCG
	}
}

Dependency "AddPassShader" = "Hidden/TerrainEngine/Splatmap/Lightmap-AddPass"
Dependency "BaseMapShader" = "Diffuse"

Fallback "Mobile/Fog of War/Diffuse"
}

as it was before:

Shader "Nature/Terrain/Diffuse" {
Properties {
	[HideInInspector] _Control ("Control (RGBA)", 2D) = "red" {}
	[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
	[HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
	[HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
	[HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
	// used in fallback on old cards  base map
	[HideInInspector] _MainTex ("BaseMap (RGB)", 2D) = "white" {}
	[HideInInspector] _Color ("Main Color", Color) = (1,1,1,1)
}
	
SubShader {
	Tags {
		"SplatCount" = "4"
		"Queue" = "Geometry-100"
		"RenderType" = "Opaque"
	}
CGPROGRAM
#pragma surface surf Lambert
struct Input {
	float2 uv_Control : TEXCOORD0;
	float2 uv_Splat0 : TEXCOORD1;
	float2 uv_Splat1 : TEXCOORD2;
	float2 uv_Splat2 : TEXCOORD3;
	float2 uv_Splat3 : TEXCOORD4;
};

sampler2D _Control;
sampler2D _Splat0,_Splat1,_Splat2,_Splat3;

void surf (Input IN, inout SurfaceOutput o) {
	fixed4 splat_control = tex2D (_Control, IN.uv_Control);
	fixed3 col;
	col  = splat_control.r * tex2D (_Splat0, IN.uv_Splat0).rgb;
	col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1).rgb;
	col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2).rgb;
	col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3).rgb;
	o.Albedo = col;
	o.Alpha = 0.0;
}
ENDCG  
}

Dependency "AddPassShader" = "Hidden/TerrainEngine/Splatmap/Lightmap-AddPass"
Dependency "BaseMapShader" = "Diffuse"

// Fallback to Diffuse
Fallback "Diffuse"
}

This is the working “Diffuse” code for vertex fragment by @shiva.js:

// Unlit shader. Simplest possible textured shader.
// - no lighting
// - no lightmap support
// - no per-material color

Shader "Mobile/Fog of War/Diffuse"
{
	Properties {
		_Color ("Main Color", Color) = (1,1,1,1)
	    _MainTex ("Texture", 2D) = "white" { }
	}
	SubShader {
	    Pass {
	 
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		 
		#include "UnityCG.cginc"
		 
		float4 _Color;
		sampler2D _MainTex;
		 
		//begin regin FOG_OF_WAR
		sampler2D _FogTex0;
		sampler2D _FogTex1;
		uniform float4 _Params;
		uniform half4 _Unexplored;
		uniform half4 _Explored;
		//end regin
		 
		struct v2f {
		    float4  pos : SV_POSITION;
		    float2  uv : TEXCOORD0;
		   
		    float2 fog : TEXCOORD2; // this is the new line to add
		};
		 
		float4 _MainTex_ST;
		 
		v2f vert (appdata_base v)
		{
		    v2f o;
		    o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
		    o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
		   
		    float4 worldPos = mul (_Object2World, v.vertex);
		    o.fog.xy = worldPos.xz * _Params.z + _Params.xy;
		   
		    return o;
		}
		 
		half4 frag (v2f i) : COLOR
		{
		    half4 c = tex2D (_MainTex, i.uv);
		   
		    half4 fog = lerp(tex2D(_FogTex0, i.fog), tex2D(_FogTex1, i.fog), _Params.w);
		    c= lerp(lerp(c * _Unexplored, c * _Explored, fog.g), c, fog.r); // where c is the fixed4 that you will return
		   
		    return c * _Color;
		}
		
		ENDCG
	    }
	}
	Fallback "Diffuse"
}

This is it, do you have any idea to solve that? (Especially in relation to the part of splats)

Solve what exactly? Are you simply looking for someone to merge the functionality for you?

Keep in mind that Surface Shaders create their own passes, so you can’t place them inside other Pass blocks.

there is any way to use lighting in vertex shader.

You don’t necessarily need to convert the surface shader to add multiple passes. The details are explained in this thread: