This shader uses the normals of the mesh to determine what texture is to be applied.
We will get to know how to access normal data in the shader as well as how to apply a texture based on it.
This is what we will end up with after getting normal data :

Now let's look the structs needed :
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
fixed4 norm : COLOR;
float4 vertex : SV_POSITION;
};As you can see I added an appdata member called float3 normal of type NORMAL, this will be used in the vertex shader to then later on pass to the fragment shader.
In the v2f struct I added a member called fixed4 norm of type COLOR, this will be used in fragment shader to do the actual work.
Let's see what the vertex shader is doing now:
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.norm.xyz = v.normal;
o.norm.w = 1.0;
o.uv = TRANSFORM_TEX(v.uv, _Tex1);
return o;
}It's taking in an appdata struct and outputting a v2f struct - which will be used in fragment shader.
We are assigning the norm value with the actual normal data from the mesh.
As norm is actually a color RGB is XYZ, so o.norm = v.normal will assign the RGB values directly and o.norm.w = 1.0 makes sure alpha is at 100%.
So if you want the output from the image you saw before you make the fragment shader output the norm value :
fixed4 frag (v2f i) : SV_Target
{
return abs(i.norm);
}We are using abs(i.norm) because we don't want dark or black parts to show up on the object.
Now we will see how to add textures based on the normal in the fragment shader.
We will end up with something that looks like this:

We need to add three texture properties:
Properties
{
_Tex1 ("Texture 1", 2D) = "white" {}
_Tex2("Texture 2", 2D) = "white"{}
_Tex3("Texture 3", 2D) = "white"{}
}What are they:
sampler2D _Tex1;
sampler2D _Tex2;
sampler2D _Tex3;
float4 _Tex1_ST;Now finally... the fragment shader:
fixed4 frag (v2f i) : SV_Target
{
fixed4 col1 = tex2D(_Tex1, i.uv);
fixed4 col2 = tex2D(_Tex2, i.uv);
fixed4 col3 = tex2D(_Tex3, i.uv);
col1 *= abs(dot(i.norm.xyz, float3(0, 0, 1)));
col2 *= abs(dot(i.norm.xyz, float3(0, 1, 0)));
col3 *= abs(dot(i.norm.xyz, float3(1, 0, 0)));
return ((col1 +col2 + col3)/3) * 1.2;
}After we take the three colors from the UV map we then multiply each of those with a value that shows how close the normal is to the X, Y & Z axis.
col1 *= abs(dot(i.norm.xyz, float3(0, 0, 1)));The dot function between the normal and an axis will return a value between -1.0 and +1.0 then we use the abs ( absolute ) function which gives only the magnitude without the sign.
We then use that value and multiply with the color.
return ((col1 +col2 + col3)/3) * 1.2;We return a color which is the average of all those colors and we multiply by a value because the image is a bit dark.
Here is the entire shader:
1Shader "BitShiftProgrammer/DirectionalColour"
2{
3 Properties
4 {
5 _Tex1 ("Texture 1", 2D) = "white" {}
6 _Tex2("Texture 2", 2D) = "white"{}
7 _Tex3("Texture 3", 2D) = "white"{}
8 }
9 SubShader
10 {
11 Tags { "RenderType"="Opaque" }
12
13 Pass
14 {
15 CGPROGRAM
16 #pragma vertex vert
17 #pragma fragment frag
18
19 #include "UnityCG.cginc"
20
21 struct appdata
22 {
23 float4 vertex : POSITION;
24 float2 uv : TEXCOORD0;
25 float3 normal : NORMAL;
26 };
27
28 struct v2f
29 {
30 float2 uv : TEXCOORD0;
31 fixed4 norm : COLOR;
32 float4 vertex : SV_POSITION;
33 };
34
35 sampler2D _Tex1;
36 sampler2D _Tex2;
37 sampler2D _Tex3;
38 float4 _Tex1_ST;
39
40 v2f vert (appdata v)
41 {
42 v2f o;
43 o.vertex = UnityObjectToClipPos(v.vertex);
44 o.norm.xyz = v.normal;
45 o.norm.w = 1.0;
46 o.uv = TRANSFORM_TEX(v.uv, _Tex1);
47 return o;
48 }
49
50 fixed4 frag (v2f i) : SV_Target
51 {
52 fixed4 col1 = tex2D(_Tex1, i.uv);
53 fixed4 col2 = tex2D(_Tex2, i.uv);
54 fixed4 col3 = tex2D(_Tex3, i.uv);
55 col1 *= abs(dot(i.norm.xyz, float3(0, 0, 1)));
56 col2 *= abs(dot(i.norm.xyz, float3(0, 1, 0)));
57 col3 *= abs(dot(i.norm.xyz, float3(1, 0, 0)));
58
59 return ((col1 +col2 + col3)/3) * 1.2;
60 }
61 ENDCG
62 }
63 }
64}