write a blog as quick as you can. do not wait for u fully understand the shader. this is what i felt. haha, just like there many pragma error in my blog, but who cares, this is my way.
as you will forget some important things. and you will interrupt your good hobby. last you will forget how you arrive the high point. so let me publish this blog. there are some errors, welcome to u to inform me.
first, traditionally, we are used to write one file to contains all the effect. but if we have many shaders, and many parts of them are the same, we can find we do the same thing. so we think a method to solve this fabour thing. we can extract the same parts to a different file. just like C++’s #include or java’s import or C#’s using.
so let me introduce a simple shader —— rim shader to explain this key knowledge.
for clearly compare the difference between one shader and one shader that is splitted to different parts. we firstly give the one shader. the code is below:
Shader "Course/RimEffect"
{
Properties
{
_MainTex("Main Texture", 2D)="white"{} //diffuse texture
_RimColor("RimColor", Color)=(1,1,1,1) //edge color
_RimPower("RimPower",Range(0,10))=0 //edge color strength factor
}
SubShader
{
CGPROGRAM
#pragma surface surf Lambert //use the lambert lighting mode in unity
// self defined input structure
struct Input
{
float2 uv_MainTex;
float3 viewDir;
};
// declare the variables we will use
sampler2D _MainTex;
half _RimPower;
half _RimWidth;
half4 _RimColor;
void surf(Input IN, inout SurfaceOutput o)
{
// 1, sample the diffuse color
half4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo += tex.rgb;
// 2, calculate the rim color
half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
o.Emission = pow(rim, _RimPower) * _RimColor.rgb;
}
ENDCG
}
}
second, we will split the variables and function to different files.
Variables.cginc
#ifndef VARIABLES
#define VARIABLES
struct Input
{
float2 uv_MainTex;
float3 viewDir;
};
sampler2D _MainTex;
half _RimPower;
half4 _RimColor;
#endif
as you can see we use ifndef and define and endif. this will make sure there is only once be included. avoid duplicated variables. in the file.
2, put the rim function in Function.cginc file.
#ifndef FUNCTIONS
#define FUNCTIONS
#include "Variables.cginc"
half3 CalcRimEffect(Input IN, half4 tex, SurfaceOutput o)
{
half rim = 1.0 - saturate(dot(normalize(IN.viewDir), o.Normal));
return pow(rim, _RimPower) * _RimColor.rgb;
}
#endif
then, we can delete some parts in shader file , and must include these two files Variables.cginc and Functions.cginc in the shader file.
Shader "Course/RimEffect"
{
Properties
{
_MainTex("Main Texture", 2D)="white"{} //diffuse texture
_RimColor("RimColor", Color)=(1,1,1,1) //edge color
_RimPower("RimPower",Range(0,10))=0 //edge color strength factor
}
SubShader
{
CGPROGRAM
#pragma surface surf Lambert //use the lambert lighting mode in unity
#include "Functions.cginc" //include Functions.cginc, Variables.cginc can not be included, because
//it is included in Functions.cginc
void surf(Input IN, inout SurfaceOutput o)
{
// 1, sample the diffuse color
half4 tex = tex2D(_MainTex, IN.uv_MainTex);
o.Albedo += tex.rgb;
// 2, calculate the rim color
o.Emission = CalcRimEffect(IN, tex, o);
}
ENDCG
}
}
ok, let’s see the result or effect or rim. pic is posted below.
the inspector panel is like this:
you can select one color for shader, and change the rimpower factor. you can fiind this power value can change the color strength or width of the edge. the smaller factor the blur effect. the bigger the clear effect.
oh, my god, i forgot the most important knowledge, the file directory, in unity the include shader’s cginc. just like this:
if you put Functions.cginc and Variables.cginc in other directory , you should modify the #include path. some times, you will use ../../xxx/Funcitons.cginc, what’s the meaning of .., that is the up or pre folder. and the one . means the current folder.