课时52 Fragment shader - 边缘泛光shader 1

  • 课时52 Fragment shader - 边缘泛光shader 1

1.颜色的变换主要由法线N和视向量V有关。

2.代码:

 
Shader "Custom/Lesson52"
{ 
	//课时52 Fragment shader - 边缘泛光shader 1
	Properties{
		_Scale("Scale",Range(1,8)) = 2
	}
 	SubShader
	{ 
		Tags{"Queue"="Transparent"}
		Blend SrcAlpha OneMinusSrcAlpha  
		ZWrite off //否则交叉部分变黑

		Pass
		{
			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag
  
			float _Scale;

			struct v2f{
				float4 pos:POSITION;
				float3 normal:TEXCOORD0;
				float4 vertex:TEXCOORD1;
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex); 
				o.normal=v.normal;
				o.vertex=v.vertex;
				return o;  
			} 
 
			fixed4 frag (v2f IN):COLOR
			{   
				float3 N=normalize(UnityObjectToWorldNormal(IN.normal));
				float3 V=normalize(WorldSpaceViewDir(IN.vertex));// UnityWorldSpaceViewDir(IN.vertex);
				float bright=1-saturate(dot(N,V));

				bright=pow(bright,_Scale);

				return fixed4(1,1,1,1)*bright;
			}  
			ENDCG
		}
	}
}

效果:

  • 课时53 Fragment shader - 边缘泛光shader 2

1.使用多个Pass通道融合的方式,实现外边缘泛光效果。blend操作说明见:ShaderLab: Blending 

2.第一个通道沿着法线向外延展n个像素,渲染从内向外发光效果,设置混合模式为叠加;第二个通道不扩展像素,只渲染纯白色,设置令第一个通道结果减去第二通道结果;第三个通道不扩展像素,渲染从外向内发光效果,设置混合模式为叠加。

3.代码:

 
Shader "Custom/Lesson53"
{ 
	//课时53 Fragment shader - 边缘泛光shader 2
	Properties{
		_MainColor("MainColor",Color)=(1,1,1,1)
		_Scale("Scale",Range(1,8)) = 2
		_Outer("Outer",range(0,1))=0.2
	}
 	SubShader
	{ 
		Tags{"Queue"="Transparent"}
		

		Pass
		{
			Blend SrcAlpha OneMinusSrcAlpha  
			ZWrite off //否则交叉部分变黑

			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag

			fixed4 _MainColor;
			float _Scale;
			float _Outer;
			
			struct v2f{
				float4 pos:POSITION;
				float3 normal:TEXCOORD0;
				float4 vertex:TEXCOORD1;
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v.vertex.xyz+=v.normal*_Outer;
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex); 
				o.normal=v.normal;
				o.vertex=v.vertex;
				return o;  
			} 
 
			fixed4 frag (v2f IN):COLOR
			{   
				float3 N=normalize(UnityObjectToWorldNormal(IN.normal));
				float3 V=normalize(WorldSpaceViewDir(IN.vertex));// UnityWorldSpaceViewDir(IN.vertex);
				float bright=saturate(dot(N,V));

				bright=pow(bright,_Scale);

				_MainColor.a*=bright;
				return _MainColor;
			}  
			ENDCG
		}
		//=======================第二通道==================================
		Pass
		{
			BlendOp revsub //反转减法,即用目标(已渲染)减掉源(本通道)
			Blend DstAlpha One  //目标乘以1,源乘以目标的Alpha(然后相减)
			ZWrite off //否则交叉部分变黑

			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag

			struct v2f{
				float4 pos:POSITION;
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex);  
				return o;  
			} 
 
			fixed4 frag (v2f IN):COLOR
			{   
				return float4(1,1,1,1);
			}  
			ENDCG
		}
		//========================第三通道=================================
		Pass
		{
			// Blend zero one  
			Blend SrcAlpha OneMinusSrcAlpha  
			ZWrite off //否则交叉部分变黑

			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag
  
			float _Scale;

			struct v2f{
				float4 pos:POSITION;
				float3 normal:TEXCOORD0;
				float4 vertex:TEXCOORD1;
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex); 
				o.normal=v.normal;
				o.vertex=v.vertex;
				return o;  
			} 
 
			fixed4 frag (v2f IN):COLOR
			{   
				float3 N=normalize(UnityObjectToWorldNormal(IN.normal));
				float3 V=normalize(WorldSpaceViewDir(IN.vertex));// UnityWorldSpaceViewDir(IN.vertex);
				float bright=1-saturate(dot(N,V));

				bright=pow(bright,_Scale);

				return fixed4(1,1,1,1)*bright;
			}  
			ENDCG
		}
	}
}

效果:

  • 课时54 Fragment shader - 片段级模型动态变色 1

1.需求:实现模型上下部分不同颜色,界限分明的效果。

2.代码:

 
Shader "Custom/Lesson54"
{ 
	//课时54 Fragment shader - 片段级模型动态变色 1
	Properties{
		_MainColor("MainColor",Color)=(1,1,1,1)
		_SecondColor("SecondColor",Color)=(1,1,1,1)
		_Center("Center",Range(-0.5,0.5))=0
	}
 	SubShader
	{  
		Pass
		{ 
			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag

			fixed4 _MainColor;
			fixed4 _SecondColor;
			float _Center;
			
			struct v2f{
				float4 pos:POSITION;
				float y:TEXCOORD0;//建议不要使用COLOR语义,否则可能舍弃负数
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex); 

				// if(v.vertex.y<0)
				// {
				// 	o.col=_MainColor;
				// }else
				// {
				// 	o.col=_SecondColor;
				// }
				o.y=v.vertex.y;
				
				return o;  
			} 
 
			fixed4 frag (v2f IN):COLOR
			{   
				fixed4 col=(0,0,0,0);
				if(IN.y>_Center)
				{
					col=_MainColor;
				}else
				{
					col=_SecondColor;
				}

				return col;
			}  
			ENDCG
		}
	}
}

效果:

  • 课时55 Fragment shader - 片段级模型动态变色 2

1.需求:在上个需求基础上,增加融合范围。

2.代码:

 
Shader "Custom/Lesson55"
{ 
	//课时55 Fragment shader - 片段级模型动态变色 2
	Properties{
		_MainColor("MainColor",Color)=(1,1,1,1)
		_SecondColor("SecondColor",Color)=(1,1,1,1)
		_Center("Center",Range(-0.7,0.7))=0
		_R("R",Range(0,0.5))=0.2
	}
 	SubShader
	{  
		Pass
		{ 
			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag

			fixed4 _MainColor;
			fixed4 _SecondColor;
			float _Center;
			float _R;
			
			struct v2f{
				float4 pos:POSITION;
				float y:TEXCOORD0;//建议不要使用COLOR语义,否则可能舍弃负数
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex); 
 
				o.y=v.vertex.y;
				
				return o;  
			} 
			fixed4 frag (v2f IN):COLOR
			{   
				float d=IN.y-_Center;//-0.5~0.5 原始区间
				float s=abs(d);//0~0.5 原始绝对区间
				d=d/s;//-1,1 正负号

				float f=s/_R;//0~1.x 
				f=saturate(f);//0~1 缩减绝对区间
				d*=f;//-f,f 给绝对区间加正负号

				d=d/2+0.5;//变换至0~1区间
				
				return lerp(_MainColor,_SecondColor,d);
			}  
			fixed4 frag333 (v2f IN):COLOR
			{   
				fixed4 col=(0,0,0,0);
				if(IN.y>_Center+_R)
				{
					col=_MainColor;
				}else if(IN.y>_Center&&IN.y<_Center+_R)
				{
					float d=IN.y-_Center;//0~_R
					d=d/_R/2+0.5;//0.5~1
					col=lerp(_SecondColor,_MainColor,d);
				}else if(IN.y<_Center&&IN.y>_Center-_R)
				{
					float d=-IN.y+_Center;
					d=d/_R/2+0.5;//0.5~1
					col=lerp(_MainColor,_SecondColor,d);
				}else
				{
					col=_SecondColor;
				}
				return col;
			}  
			fixed4 frag222 (v2f IN):COLOR
			{   
				fixed4 col=(0,0,0,0);
				float d=IN.y-_Center;//范围-1~1
				d=d/abs(d);//范围-1,1
				d=d/2+0.5;//范围0,1
				
				col=lerp(_MainColor,_SecondColor,d); 

				return col;
			}  
			fixed4 frag111 (v2f IN):COLOR
			{   
				fixed4 col=(0,0,0,0);
				if(IN.y>_Center)
				{
					col=_MainColor;
				}else
				{
					col=_SecondColor;
				}

				return col;
			}  
			ENDCG
		}
	}
}

效果:

  • 课时56 Fragment shader - 片段级模型动态变色 3

1.Unity内模型面数超过65534个会自动分割出几个子模型。这个案例中,车身模型被分成3个,子模型的坐标原点位置和朝向是一致的,即在一个坐标空间内,所以可以不考虑模型拆分问题。

2.需求:使车身模型在x轴向上分成两种颜色。

3.首先计算出模型在x轴向上的值范围:求得范围±0.05。由此得出最大融合半径=0.05*2*0.2=0.02。中心范围±0.07。

	/// <summary>
    /// 求得mesh内位于X轴向上,最大和最小值。模型缩放不影响结果。
    /// </summary>
    /// <param name="mf">网格</param>
	private void checkVertex(MeshFilter mf)
	{
        Vector3[] verts = mf.mesh.vertices;
        float max = verts.Max(v => v.x);
        float min = verts.Min(v => v.x);
        Debug.Log("最大==" + max);
        Debug.Log("最小==" + min);
    }

4.修改上节课shader为y轴向

 
Shader "Custom/Lesson56"
{ 
	//课时56 Fragment shader - 片段级模型动态变色 3
	Properties{
		_MainColor("MainColor",Color)=(1,1,1,1)
		_SecondColor("SecondColor",Color)=(1,1,1,1)
		_Center("Center",Range(-0.07,0.07))=0
		_R("R",Range(0,0.02))=0.001
	}
 	SubShader
	{  
		Pass
		{ 
			CGPROGRAM    
			#include "unitycg.cginc" 
			#pragma vertex vert
			#pragma fragment frag

			fixed4 _MainColor;
			fixed4 _SecondColor;
			float _Center;
			float _R;
			
			struct v2f{
				float4 pos:POSITION;
				float x:TEXCOORD0;//建议不要使用COLOR语义,否则可能舍弃负数
			};
 		 
			v2f  vert (appdata_base v) 
			{
				v2f o; 
				o.pos=UnityObjectToClipPos(v.vertex); 
 
				o.x=v.vertex.x;
				
				return o;  
			} 
			fixed4 frag (v2f IN):COLOR
			{   
				float d=IN.x-_Center;//-0.5~0.5 原始区间
				float s=abs(d);//0~0.5 原始绝对区间
				d=d/s;//-1,1 正负号

				float f=s/_R;//0~1.x 
				f=saturate(f);//0~1 缩减绝对区间
				d*=f;//-f,f 给绝对区间加正负号

				d=d/2+0.5;//变换至0~1区间
				
				return lerp(_MainColor,_SecondColor,d);
			}   
			ENDCG
		}
	}
}

5.效果:

6.进一步改进为Surfaceshader。

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'


Shader "Custom/Lesson56"
{
	//课时56 Fragment shader - 片段级模型动态变色 3
	Properties{
		_MainColor("MainColor",Color)=(1,1,1,1)
		_SecondColor("SecondColor",Color)=(1,1,1,1)
		_Center("Center",Range(-0.07,0.07))=0
		_R("R",Range(0,0.02))=0.001
		_Glossiness("Smoothness",Range(0,1))=0
		_Metallic("Metallic",Range(0,1))=0
	}
 	SubShader
	{
		Tags { "RenderType"="Opaque" }
		LOD 200

		CGPROGRAM
		//等同于:pragma surface surf Standard vertex:vert fullforwardshadows
		//有时会不识别vert函数,但不报错
		#pragma surface surf Standard  fullforwardshadows vertex:vert

		#pragma target 3.0

		sampler2D _MainTex;

		fixed4 _MainColor;
		fixed4 _SecondColor;
		float _Center;
		float _R;
		half _Glossiness;
		half _Metallic;
		//surfaceshader的Input声明可以不加语义
		struct Input{
			float2 uv_MainTex;
			float x;//可省略TEXCOORD0语义
		};

		void vert(inout appdata_full v,out Input o)
		{
			o.uv_MainTex=v.texcoord.xy;
			o.x=v.vertex.x;
			// v.vertex=UnityObjectToClipPos(v.vertex);
		}

		void surf(Input IN,inout SurfaceOutputStandard o){
			fixed4 c=tex2D(_MainTex,IN.uv_MainTex);
			o.Albedo=c.rgb;
			o.Metallic=_Metallic;
			o.Smoothness=_Glossiness;
			o.Alpha=c.a;
				float d=IN.x-_Center;//-0.5~0.5 原始区间
				float s=abs(d);//0~0.5 原始绝对区间
				d=d/s;//-1,1 正负号

				float f=s/_R;//0~1.x
				f=saturate(f);//0~1 缩减绝对区间
				d*=f;//-f,f 给绝对区间加正负号

				d=d/2+0.5;//变换至0~1区间

				o.Albedo.rgb *= lerp(_MainColor,_SecondColor,d)*2;

		}
		ENDCG
	}
	Fallback "Diffuse"
}

效果:

  • 课时57 Fragment shader - 2D纹理采样 1

1.图片的Wrap Mode设置分为:Repeat和Clamp,Repeat表示超出0~1采样区间采用平铺,可以用于平铺材质,Clamp表示超出后用最边缘像素填充。

2.图片的Filter Mode设置分为:No Filter(无过滤)就近点采样,Bilinear(双线性过滤)临近四个点插值采样,Trilinear(三线性过滤)三线性和双线性的差别在于三线性可以根据mip maps的变化来。

3.代码:

Shader "Custom/Lesson57"
{
	//课时57 Fragment shader - 2D纹理采样 1
	 Properties{
		 _MainTex("MainTex",2D)="white"{}
		 _U("U",Range(-0.01,0.01))=0
	 }
 	SubShader
	{
		pass{

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"

		sampler2D _MainTex;
		float2 uv_MainTex;
		float _U;

		struct v2f{
			float4 pos:POSITION;
			float2 uv:TEXCOORD0;
		};


		v2f vert(appdata_base v)
		{
			v2f o;
			o.pos=UnityObjectToClipPos(v.vertex);
			o.uv=v.texcoord.xy;
			return o;
		}

	 	fixed4 frag(v2f IN):COLOR
		 {
			 fixed4 color=tex2D(_MainTex,IN.uv);
			 return color;
		 }
		ENDCG
		}
	}
	Fallback "Diffuse"
}

效果:未实现Tiling和Offset功能。

  • 课时58 Fragment shader - 2D纹理采样 2

1.需求:启用图片的平铺和偏移变换功能。

2.注意知识点:非表面Shader,需要声明图片变换属性name_ST,顶点函数中使用宏TRANSFORM_TEX(o.texcoord,name)得到uv值,片元函数中调用tex2D(name,IN.uv)。表面Shader,在Input结构体中声明uv_name,在surface函数中调用tex2D(name,IN.uv_name)

3.代码

Shader "Custom/Lesson58"
{
	//课时58 Fragment shader - 2D纹理采样 2
	 Properties{
		 _MainTex("MainTex",2D)="white"{}
	 }
 	SubShader
	{
		pass{

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"

		sampler2D _MainTex;
		//在片元函数中,纹理坐标对应uv_MainTex,并且声明在Input结构体内,直接在片元中调用tex2D(_Maintex,IN.uv_MainTex)
		//在TRANSFORM_TEX宏中显式用到_MainTex,隐式用到_MainTex_ST,后在片元中调用tex2D(_Maintex,o.uv)
		float4 	_MainTex_ST;

		// float tiling_x=1;
		// float tiling_y=1;
		// float offset_x;
		// float offset_y;

		struct v2f{
			float4 pos:POSITION;
			float2 uv:TEXCOORD0;
		};

		v2f vert(appdata_base v)
		{
			v2f o;
			o.pos=UnityObjectToClipPos(v.vertex);
			//相当于 o.uv=v.texcoord.xy*_MainTex_ST.xy+_MainTex_ST.zw;
			o.uv=TRANSFORM_TEX(v.texcoord, _MainTex);
			
			return o;
		} 

	 	fixed4 frag(v2f IN):COLOR
		 {
			 fixed4 color=tex2D(_MainTex,IN.uv);
			 return color;
		 }
		ENDCG
		}
	}
	Fallback "Diffuse"
}

效果:

  • 课时59 Fragment shader - 2D纹理采样 3

1.搭建待烘焙场景,灯光设为baked模式,模型设为lightmap static。Lighting-Scene-EnvironmentLighting-Ambient GI设为Baked,然后点积生成光照贴图。

2.然后使用第58课的shader,显示下面的效果。要求能够支持光照贴图。

3.Unity官方文档,见Rendering Optimizations

4.代码:

// Upgrade NOTE: commented out 'float4 unity_LightmapST', a built-in variable
// Upgrade NOTE: commented out 'sampler2D unity_Lightmap', a built-in variable

// Upgrade NOTE: commented out 'float4 unity_LightmapST', a built-in variable
// Upgrade NOTE: commented out 'sampler2D unity_Lightmap', a built-in variable
// Upgrade NOTE: replaced tex2D unity_Lightmap with UNITY_SAMPLE_TEX2D

Shader "Custom/Lesson59"
{
	//课时59 Fragment shader - 2D纹理采样 3
	 Properties{
		 _MainTex("MainTex",2D)="white"{}
	 }
 	SubShader
	{
		pass{

		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"

		sampler2D _MainTex;
		//unity会自动传参,新版Unity不需重复声明
		// sampler2D unity_Lightmap;
		//对应unity_Lightmap,新版Unity不需重复声明
		// float4 unity_LightmapST;
		float4 	_MainTex_ST;

		struct v2f{
			float4 pos:POSITION;
			float2 uv:TEXCOORD0;
			float2 uv2:TEXCOORD1;
		};

		v2f vert(appdata_full v)
		{
			v2f o;
			o.pos=UnityObjectToClipPos(v.vertex);
			o.uv=TRANSFORM_TEX(v.texcoord, _MainTex);
			o.uv2=v.texcoord1*unity_LightmapST.xy+unity_LightmapST.zw;
			
			return o;
		} 

	 	fixed4 frag(v2f IN):COLOR
		 {
			 //先对颜色贴图采样,再解码
			 float3 lm=DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,IN.uv2));
			 fixed4 color=tex2D(_MainTex,IN.uv);
			 color.rgb*=lm*1.5;
			 return color;
		 }
		ENDCG
		}
	}
	Fallback "Diffuse"
}

效果:比标准着色器效果偏蓝

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值