简单易懂的Unity5 Shader着色器入门教程

如何使用属性

Shader"MyShader"{ //这里是 文件名

	Properties{
		//属性  
		_Color("_Color",Color) = (1,1,1,1)//四维向量								  float4

		_Vector("Vector",Vector) = (1,2,3,4) //四维向量							  float4

		_Int("Int",int) = 12     //int值											  float

		_Float("Float",Float) = 234.3 //float值									  float

		_Range("Range",Range(1,23)) = 3  // 滑动条 大小从1到23  默认为3             float

		_2D("Texter",2D) = "white"{}  //2D图片的texter 如果什么都不指定 默认为白色   sampler2D

   	    _Cube("Cube",Cube) = "white"  {}  //立方体文理  一般用于天空空盒子           samplerCube

		_3D("3D",3D) = "black"{}   //2D 的纹理                                     sampler3D
	}
		///子的shader   SubShader可以有很多个   显卡运行效果的时候,从第一个subShader开始 ,
		//如果第一个SubShader里面的效果都可以实现 那么就是用第一个SUbShade,如果显卡发现SubShader里面的效果他实现不了,
		//他会自动去运行下一个SubShader
		SubShader{
		//至少有一个Pass块
		Pass{
		//在这里编写SHader代码   或者HLSLPROGRAM

		CGPROGRAM
		//使用CG语言编写Shader


		//CGPROGRAM
		// 属性要从新定义一遍   里面对应的是float4  对应 Vector4
		 float4 _Color ;
		 float4 _Vector;  //可以代替为 half3  或者 fixed
		 float3 t1;
		 float2 t;
		 float t2;
		 //float  用32位来存储   
		 //half 16位来存储  -6万-6万
		 //fixed  11为  -2到2
		 float _Int;
		 float _Float;
		 float _Range;
		 //2D 的格式
		 sampler2D _2D;
		 samplerCube _Cube;
		 sampler3D _3D;
		ENDCG

        }
	}
	//如果上面的SubShader都不能用久使用Fallback指定的shader
	Fallback "VertexLit"

}

010-创建vert和frag函数(顶点函数和片元函数)

Shader"MyShader02"{



	SubShader{
		Pass{

		CGPROGRAM
		//定点函数  这里只是声明了 顶点函数的函数名
		// 基本作用是  完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex  vert


		//片元函数  这里只是声明了 顶点函数的函数名
		//基本作用  返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag 
		//xxx返回值 
		float4 vert(float4 v:POSITION   /* float4 v:POSITION   通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法  */
		) :SV_POSITION   //:SV_POSITION 对返回值做解释说明  // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统  
		{

		//float4 pos = mul(UNITY_MATRIX_MVP,v); //完成一个矩阵到一个position的乘法运算
		//return pos;

		return  mul(UNITY_MATRIX_MVP,v);

		}
		//片元函数  返回模型对应屏幕上的每一个像素的颜色值
		fixed4 frag():SV_Target   //SV_Target 返回值 对应的屏幕颜色
		{
			return  fixed4(1,1,1,1);
		}

		ENDCG


		}
	}

		Fallback "VertexLit"
}

013-学习NORMAL、TEXCOORD0语义; 014-如何在片元函数和顶点函数之间传递数据

Shader"MyShader03Usestruct"{
	SubShader{
		Pass{

		CGPROGRAM
		//定点函数  这里只是声明了 顶点函数的函数名
		// 基本作用是  完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex  vert
		//片元函数  这里只是声明了 顶点函数的函数名
		//基本作用  返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag 
		//a2v   application  to vertex  从应用传递到顶点 的数据
		struct a2v    //结构体 和CSharp的一样 不过也要返回 v:POSITION
		{
		/* float4 v:POSITION   通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法  */
		  float4 vertex:POSITION;  //告诉unity 吧模型空间下的顶点坐标给到vertex
		  float3 normal:NORMAL;// 法线  告诉unity 把模型空间下的发现法相填充给normal 
		  float4 texcoord:TEXCOORD0;  //告诉unity 把第0套纹理坐标填充给texcoord
		}; 

		//顶点函数的返回值也使用结构体
		struct v2f{
			float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明  // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统  
			float3  temp:COLOR0;
		};

		// 顶点函数 引用一个结构体  调用结构体中的  vertex
		v2f vert(a2v v) 
		{
			v2f f;
		
			f.position= mul(UNITY_MATRIX_MVP, v.vertex);
			f.temp = v.normal;  //法线 赋值
		//float4 pos = mul(UNITY_MATRIX_MVP,v); //完成一个矩阵到一个position的乘法运算
		//return pos;
		    return  f;

		}
		//片元函数  返回模型对应屏幕上的每一个像素的颜色值
		fixed4 frag(v2f f ):SV_Target   //SV_Target 返回值 对应的屏幕颜色
		{
			return fixed4(f.temp,1); //使用 法线
		}
		ENDCG
		}
	}
		//Fallback "VertexLit"
}

015-Unity中的语义有哪些


019-编写漫反射的shader代码


Shader"MyShader04Diffuse"{
	SubShader{
		Pass
		{
		Tags{"LightMode" = "ForwardBase" }
		CGPROGRAM 
#include "Lighting.cginc"  ///取得第一个直射光的颜色 _LightColor0   _WorldSpaceLightPos0 第一个直射光的位置
		//定点函数  这里只是声明了 顶点函数的函数名
		// 基本作用是  完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex  vert
		//片元函数  这里只是声明了 顶点函数的函数名
		//基本作用  返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag 

		//只有定义了LightMode 才能得到一些Unity的内置光照变量

		//a2v   application  to vertex  从应用传递到顶点 的数据
		struct a2v    //结构体 和CSharp的一样 不过也要返回 v:POSITION
		{
		/* float4 v:POSITION   通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法  */
		  float4 vertex:POSITION;  //告诉unity 吧模型空间下的顶点坐标给到vertex
		  float3 normal:NORMAL;  //取 到法线  法线在模型空间下面
		}; 

		//顶点函数的返回值也使用结构体
		struct v2f{
			float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明  // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统  
			fixed3 color : COLOR;
		};

		// 顶点函数 引用一个结构体  调用结构体中的  vertex
		v2f vert(a2v v) 
		{
			v2f f;
			f.position= mul(UNITY_MATRIX_MVP,v.vertex);   //UNITY_MATRIX_MVP 这个矩阵用来吧一个坐标从模型空间转换到剪裁空间
			//_World2Object 
		    fixed3 normalDir= normalize(mul(v.normal, (float3x3)_World2Object));     //_World2Object这个矩阵用来吧一个方向从世界空间转换到模型空间   位置变换一下就是 从模型空间转换成世界空间  

			fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  // 第一个直射光的位置  对于每一个顶点来说 光位置就是广德方向,因为光是平行光  并把它单位化 normalize


			// 漫反射 Diffuse=直射光颜色*Max(0,cos夹角(光和法线的夹角))  cosθ=光的方向 点乘 法线的方向
			fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0) ;  //定义漫反射的颜色  在"Lighting.cginc";  中取到 _LightColor0
			f.color = diffuse;
		    return  f;

		}
		//片元函数  返回模型对应屏幕上的每一个像素的颜色值
		fixed4 frag(v2f f ):SV_Target   //SV_Target 返回值 对应的屏幕颜色
		{
			return fixed4(f.color,1); //使用 法线
		}
		ENDCG
		}
	}
		//Fallback "VertexLit"
}

020-给物体添加漫反射颜色和环境光颜色控制

Shader"MyShader04Diffuse"{
	Properties{
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
	}
		SubShader{
			Pass
			{ Tags{"LightMode" = "ForwardBase" }
			CGPROGRAM
	#include "Lighting.cginc"  ///取得第一个直射光的颜色 _LightColor0   _WorldSpaceLightPos0 第一个直射光的位置
		//定点函数  这里只是声明了 顶点函数的函数名
		// 基本作用是  完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex  vert
		//片元函数  这里只是声明了 顶点函数的函数名
		//基本作用  返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag 
		fixed4 _Diffuse;  // 从新声明 一下 


		//只有定义了LightMode 才能得到一些Unity的内置光照变量

		//a2v   application  to vertex  从应用传递到顶点 的数据
		struct a2v    //结构体 和CSharp的一样 不过也要返回 v:POSITION
		{
		/* float4 v:POSITION   通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法  */
		  float4 vertex:POSITION;  //告诉unity 吧模型空间下的顶点坐标给到vertex
		  float3 normal:NORMAL;  //取 到法线  法线在模型空间下面
		}; 

		//顶点函数的返回值也使用结构体
		struct v2f{
			float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明  // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统  
			fixed3 color : COLOR;
		};

		// 顶点函数 引用一个结构体  调用结构体中的  vertex
		v2f vert(a2v v) 
		{
			v2f f;
			
			fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;  //取得 环境光

			f.position= mul(UNITY_MATRIX_MVP,v.vertex);   //UNITY_MATRIX_MVP 这个矩阵用来吧一个坐标从模型空间转换到剪裁空间
			//_World2Object 
		    fixed3 normalDir= normalize(mul(v.normal, (float3x3)_World2Object));     //_World2Object这个矩阵用来吧一个方向从世界空间转换到模型空间   位置变换一下就是 从模型空间转换成世界空间  

			fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  // 第一个直射光的位置  对于每一个顶点来说 光位置就是广德方向,因为光是平行光  并把它单位化 normalize


			// 漫反射 Diffuse=直射光颜色*Max(0,cos夹角(光和法线的夹角))  cosθ=光的方向 点乘 法线的方向
			fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0) * _Diffuse.rgb;  //定义漫反射的颜色  在"Lighting.cginc";  中取到 _LightColor0
			// _Diffuse.rgb   乘以  设置的RGB的值
			f.color = diffuse + ambient;
		    return  f;

		}
		//片元函数  返回模型对应屏幕上的每一个像素的颜色值
		fixed4 frag(v2f f ):SV_Target   //SV_Target 返回值 对应的屏幕颜色
		{
			return fixed4(f.color,1); //使用 法线
		}
		ENDCG
		}
	}
		//Fallback "VertexLit"
}

021-实现逐像素光照(漫反射)

Shader"05-Diffuse Fragment"{
	Properties{
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
	}
		SubShader{
			Pass
			{ Tags{"LightMode" = "ForwardBase" }
			CGPROGRAM
	#include "Lighting.cginc"  ///取得第一个直射光的颜色 _LightColor0   _WorldSpaceLightPos0 第一个直射光的位置
		//定点函数  这里只是声明了 顶点函数的函数名
		// 基本作用是  完成顶点坐标 从模型空间到剪裁空间的转换 (从游戏环境转换到视野相机屏幕上)
#pragma vertex  vert
		//片元函数  这里只是声明了 顶点函数的函数名
		//基本作用  返回模型对应屏幕上的每一个像素的颜色值
#pragma fragment frag 
		fixed4 _Diffuse;  // 从新声明 一下 


		//只有定义了LightMode 才能得到一些Unity的内置光照变量

		//a2v   application  to vertex  从应用传递到顶点 的数据
		struct a2v    //结构体 和CSharp的一样 不过也要返回 v:POSITION
		{
		/* float4 v:POSITION   通过语义告诉系统 我这个参数是干嘛的 比方 POSITION是告诉系统我需要顶点坐标。 操作系统会吧 POSITION传递给 V ,每一个POSITION都会调用一下这个方法  */
		  float4 vertex:POSITION;  //告诉unity 吧模型空间下的顶点坐标给到vertex
		  float3 normal:NORMAL;  //取 到法线  法线在模型空间下面
		}; 

		//顶点函数的返回值也使用结构体
		struct v2f{
			float4 position:SV_POSITION; //:SV_POSITION 对返回值做解释说明  // 然后吧V转换为剪裁空间下的顶点坐标 返回给操作系统  
			fixed3 worldNormalDir : COLOR;
		};

		// 顶点函数 引用一个结构体  调用结构体中的  vertex
		v2f vert(a2v v) 
		{
			v2f f;
			f.position= mul(UNITY_MATRIX_MVP, v.vertex);     //UNITY_MATRIX_MVP 这个矩阵用来吧一个坐标从模型空间转换到剪裁空间
			f.worldNormalDir =mul(v.normal, (float3x3)unity_WorldToObject);

		    return  f;

		}
		//片元函数  返回模型对应屏幕上的每一个像素的颜色值
		fixed4 frag(v2f f ):SV_Target   //SV_Target 返回值 对应的屏幕颜色
		{

		fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;  //取得 环境光
															//_World2Object 
		fixed3 normalDir = normalize(f.worldNormalDir);     //_World2Object这个矩阵用来吧一个方向从世界空间转换到模型空间   位置变换一下就是 从模型空间转换成世界空间  

		fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);  // 第一个直射光的位置  对于每一个顶点来说 光位置就是广德方向,因为光是平行光  并把它单位化 normalize
																// 漫反射 Diffuse=直射光颜色*Max(0,cos夹角(光和法线的夹角))  cosθ=光的方向 点乘 法线的方向
		fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0) * _Diffuse.rgb;  //定义漫反射的颜色  在"Lighting.cginc";  中取到 _LightColor0
																						  // _Diffuse.rgb   乘以  设置的RGB的值
		fixed3 tempColor= diffuse + ambient;

		return fixed4(tempColor,1); //使用 法线
		}
		ENDCG
		}
	}
	 Fallback "Diffuse"
}



猜你喜欢

转载自blog.csdn.net/qq_36848370/article/details/80405749