Unity3D基于CG的Shader基础(二)

3.顶点和片段着色器:

实现颜色过渡,

添加边框

//顶点片段着色器的工作流程:
//1.首先:vertexProgram收到系统传递给他的模型数据
//3.然后,把这些数据处理成我们后续需要的数据(至少包含定点的位置信息),其他的数据还包含一些文理的UV坐标以及他们的要传递的fragmentPraogram的数据
//3.然后,系统对vertexProgram输入的顶点数据进行插值计算,并将差值结果传递给frgmentProgram,最后fragemntProgram根据这些插值计算屏幕上的显示的像素颜色
Shader "CustomLearn/VertexAndFragShader" {
	Properties{
	//颜色设置
		_myColor("Color",color) = (1,1,1,1)
		//边框距离
		_outLine("OutLine",Range(0,1)) = 0.1
	}
	SubShader{
	//渲染不透明物体,IgnoreProjector指不受投影的影响
		Tags{
			"Queue" = "Geometry" "RenderType" = "Opaque" "IgnoreProjector" = "True"
		}
		//第一个通道。用来渲染物体表面的颜色
		PASS{
			CGPROGRAM
			//告诉程序定义一个顶点着色器
			#pragma vertex vert
			//定义一个片段着色器
			#pragma fragment frag
			//使用顶点和片段的CG时,需要引入头文件UnityCG.cginc
			#include "UnityCG.cginc"
			//定义vertex to fragment结构体
			//v2f:顶点程序到片段程序的信息传递
			//本结构体传递的是位置和颜色参数
			fixed4 _myColor;
				struct v2f{
				//该结构体中还可以包含其他的一些成员变量
				//1.float4 vertex:POSTION 顶点位置
				//2.float3 normal:POSTION 顶点法线
				//3.float4 texcoord:TEXCOORD0 第一UV坐标
				//4.float4 texcoord:TEXCOORD1 第二UV坐标
				//5.float4 tangent:TANGENT切线向量(一般是用在法线贴图中)
				//6.float4 color:COLOR 每个顶点的颜色

				//SV_POSITON:SV前缀的变量代表SystemValue
					float4 pos:SV_POSITION;
					float3 color:COLOR;
				};
				//顶点函数,参数十一结构体,返回值也是一个结构体
				//appdata_full是“UnityCG.cginc”的结构体类型
				//顶点函数的参数类型可以有:
				//appdata_base:包含顶点位置,法线和一个纹理坐标
				//appdata_full:包含顶点的位置,法线和两个纹理坐标
				//appdata_tan:包含顶点位置,法线,切线和一个的纹理坐标
				//appdata_img:包含位置和一个纹理坐标
				v2f vert(appdata_full v) {
					v2f o;
					//UNITY_MATRIX_MVP表示当前模型视图投影的矩阵
					//UNITY_MATRIX_MV表示当前模型的视图矩阵
					//UNITY_MATRIX_V表示当前视图矩阵
					//UNITY_MATRIX_P表示当前视图投影矩阵
					//UNITY_MATRIX_T_MV:转置模型视图矩阵
					//UNITY_MATRIX_IT_MV:表示逆转置视图矩阵
					//mul:表示矩阵相除函数 
					o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
					//彩虹色
					o.color = v.vertex*0.8+0.5;
					//纯色
//					o.color = v.normal*0.4+0.5;
					return o;
				}
				//片段函数,参数是v2f的结构体类型
			fixed4 frag(v2f i):COLOR{
			return fixed4(i.color*_myColor,1);
		}
		ENDCG
		}
		//第二个通道,用来渲染模型的边框
		pass{
			Name "Bordor"
			Tags{
			"LightModel" = "ForwardBase"}
			//前方剔除
			CULL Front
			Lighting On
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			//编译指令:编译正向渲染的基础通道
			//用于正向渲染中,应用环境关照,主方向光照和顶点所需要的变体
			#pragma multi_compile_fwdbase

			#include "UnityCG.cginc"
			//float相当于一个Range类型
			float _outLine;
			struct a2v{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
			};
			struct v2f{
				float4 pos:POSITION;
			};
			v2f vert(a2v v){
			v2f o;
			float4 pos = mul(UNITY_MATRIX_MV,v.vertex);
			float3 normal = mul(UNITY_MATRIX_IT_MV,v.normal);
			pos = pos+float4(normalize(normal),0)*_outLine;
			o.pos = mul(UNITY_MATRIX_P,pos);
			return o;
			}
			fixed4 frag(v2f i):COLOR{
			 	return fixed4(0,0,0,1);
			}

			ENDCG
		
		}
	}
}
例子:

1.Earth的纹理和云层:

Shader "CustomPractice/Earth" {
	Properties {
		//地球纹理
		_EarthTex("EarthTex",2D) = "white"{}
		//云的纹理
		_CloudTex("CloudTex",2D) = "white"{}
	}
	SubShader {
		Tags{"RenderType" = "Transparent"}
		LOD 200
		Pass{
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"
		sampler2D _EarthTex;
		sampler2D _CloudTex;

		struct v2f{
		//顶点的位置
			float4 vertex:POSITION;
			//纹理的坐标
			fixed4 texcoord:TEXCOORD0;
		};
		void vert(inout v2f v){
			v.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
		}
		fixed4 frag(v2f v):COLOR{
			//渲染出地球
			fixed u = v.texcoord.x+_Time*0.3;
			float2 uv = float2(u,v.texcoord.y);
			fixed4 earthColor = tex2D(_EarthTex,uv);

			//渲染出云层
			fixed uc = v.texcoord.x+_Time*0.5;
			float2 uvc = float2(uc,v.texcoord.y);
			fixed4 cloudColor = tex2D(_CloudTex,uvc);
			cloudColor = cloudColor.r*fixed4(1,1,1,1);

			//取地球和云颜色的插值
			return lerp(earthColor,cloudColor,0.5);
		}
		ENDCG
		}
	}
	FallBack "Diffuse"
}

2.流水的效果

Shader "CustomPractice/River" {
	Properties {
		//设置颜色值
		_Color("Color",color) = (1,1,1,1)
		//设置纹理
		_MainTex("Albeo(RGB)",2D) = "white"{}
		//水流速度X
		_RiverSpeedX("X_Speed",Range(2,10)) = 5
		//水流速度
		_RiverSpeedY("Y_Speed",Range(2,10))= 5
	}
	SubShader {
		Tags{"RenderType" = "Opaque"}
		CGPROGRAM
		//使用漫反射的光照模型
		#pragma surface surf Lambert
		//CG程序中要使用外部输入的值,定义变量是,一定要与属性里面的变量名一致
		sampler2D _MainTex;
		fixed4 _Color;
		fixed _RiverSpeedX;
		fixed _RiverSpeedY;

		//输入结构体
		struct Input{
			float2 uv_MainTex;

		};
		void surf(Input IN,inout SurfaceOutput o){
			fixed xSpeed = _RiverSpeedX*_Time;
			fixed ySpeed = _RiverSpeedY*_Time;
			//使用内置的_Time变量来根据运行时间滚动Texture
			fixed2 uv = IN.uv_MainTex+fixed2(xSpeed,ySpeed);

			fixed4 c = tex2D(_MainTex,uv)*_Color;

			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}

		ENDCG
	}
	FallBack "Diffuse"
}

3.三种任务模型不同效果的对比

(1):法线贴图

Shader "CustomPractice/David01" {
	Properties {
		_MainTex("MainTexture",2D) = "white"{}
	}
	SubShader {
		Tags{"RenderType" = "Opaque"}
		Pass{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			sampler2D _MainTex;
			struct v2f{
				float4 vertex:POSITION;
				fixed4 texcoord:TEXCOORD0;
			};
			void vert(inout v2f v){
			//将模型中的点转到屏幕中的位置
				v.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
			}

				fixed4 frag(v2f v):COLOR{
				//片段方法:负责每个顶点在屏幕中的颜色
				//通过纹理坐标在纹理图片上进行采样,进行输出
				return tex2D(_MainTex,v.texcoord);
				}
			ENDCG
		}
	}
	FallBack "Diffuse"
}

(2)透明

Shader "CustomPractice/David02" {
	Properties {
		_MainTex("Albedo(RGB)",2D) = "white"{}
		_LogoTex("LogoTexture",2D) = "white"{}
	}
	SubShader {
		Tags{"RenderType" = "Transparent"}
		//透明设置
		Blend SrcAlpha OneMinusSrcAlpha
		Pass{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.CGINC"
			sampler2D _MainTex;
			sampler2D _LogoTex;
			void vert(inout appdata_base v){
				v.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
			}
			fixed4 frag(appdata_base v):COLOR{
				fixed4 col = tex2D(_MainTex,v.texcoord);
				fixed4 logo = tex2D(_LogoTex,v.texcoord);
				return col*logo;
			}
			ENDCG
		}
	}
	FallBack "Diffuse"
}

(3)卡通

Shader "CustomPractice/David03" {
	Properties {
		_MainTex("MainTexture",2D) = "white"{}
		_BumpTex("BumpTexture",2D) = "white"{}
		_EmssionColor("EmssionColor",Color) = (1,1,1,1)
		isEnter("IsEnter",int) = 0
		//卡通度
		Cartoon("Cartoon",Range(-0.05,0.05)) = 0.00
	}
	SubShader {
		Tags{"RenderType" = "Opaque"}
		CGPROGRAM
			//自定义光照,模型
			#pragma surface surf CustomLighting vertex:vert
			//主纹理
			sampler2D _MainTex;
			//法线纹理
			sampler2D _BumpTex;
			//高光颜色
			fixed4 _EmssionColor;
			//判断条件
			fixed isEnter;
			//缩放系统
			float Cartoon;

			struct Input{
				fixed2 uv_MainTex;
				fixed2 uv_BumpTex;
				//视觉方向
				float3 viewDir;
			};
			//注意:自定义光照模型名字前一定要加Lighting
			half4 LightingCustomLighting(SurfaceOutput o,half3 lightDir,half atten){
				half4 result;
				half4 nDot = dot(lightDir,o.Normal);
				nDot = nDot*0.5+0.5;
				//_LightColor0:表示当前光照颜色,由系统填充
				result.rgb = o.Albedo * _LightColor0.rgb * nDot*atten;
				return result;
			}
			//顶点方法:所有纹处理完之后才会执行这个方法来移动顶点
			void vert(inout appdata_full v){
				v.vertex.xyz+= v.normal.xyz*Cartoon;
			}

			 void surf(Input IN,inout SurfaceOutput o){
			 	fixed4 albedo = tex2D(_MainTex,IN.uv_MainTex);
			 	o.Albedo = albedo;
			 	//采样法线纹理
			 	fixed4 bump = tex2D(_BumpTex,IN.uv_BumpTex);
			 	if(isEnter>0){
			 	//求视觉方向上的单位向量
			 		float3 view = normalize(IN.viewDir);
			 		//计算法线和视觉方向上的点积
			 		float value = dot(view,o.Normal);
			 		//限制一下范围
			 		value = 1-saturate(value);
			 		//边缘视觉高光现象
			 		o.Emission=_EmssionColor*value*isEnter;
			 	}
			 }
			 ENDCG
	}
	FallBack "Diffuse"
}
第一个是系统提供的Shader。

====================================================================================================================

下面是对上次一个用表面着色器写的云图的修正

Shader "CustomLearn/Five 1" {
	Properties{
		_MainTex("Albedo RGB", 2D) = "white"{}
		_Color("Color", color) = (0,0,0,1)
		_Alpha("Alpha", Range(0.5,1)) = 0.6
		_SpeedX("X_Speed",Range(0.5,10)) = 0.6
		_SpeedY("Y_Speed",Range(0.5,10)) = 0.6
	}

	SubShader{
		Tags {"RenderType" = "Transparent"}
		LOD 200

		CGPROGRAM
		//alpha 便是透明度
		#pragma surface surf Lambert alpha
		sampler2D _MainTex;
		fixed4 _Color;
		half _Alpha;
		half _SpeedX;
		half _SpeedY;

		struct Input{
			float2 uv_MainTex;
		};

		void surf(Input IN, inout SurfaceOutput o){
			fixed  xSpeed = _SpeedX * _Time;
			fixed  ySpeed = _SpeedY * _Time;

			fixed2 uv = IN.uv_MainTex - fixed2(xSpeed,ySpeed);
			fixed4 c = tex2D(_MainTex, uv);
			o.Albedo = _Color * c.rgb;
//			o.Alpha = _Color.a * c.a * _Alpha;
			o.Alpha = c.a;
		}

		ENDCG
	}

	FallBack "Diffuse"
}
效果图太大了没传上来……

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值