unityShader的编写

一:基础的结构

着色代码一般依托于材质上的体现,在一般的情况下,都需要先创建一个材质,在着色器的代码给与到材质上,再把材质给与到物体上。

js 复制代码
Shader "myshader/01 myshader"   //shader的名字,这个名字可以和文件的名字不一样,斜线前面为文件夹的路径
{       //外部读取的到的文件全部保存到这里
	Properties
	{
		//属性,可以在外面的输入
		_Color("Color",Color) = (1,1,1,1)     //默认值   第一个_Color是代码中显示的名字,第二个Color是unity显示的名字,第三个Color是类型,由4个只组成rgba
		_Vector("Vertor",Vector) = (1,2,3,4)  //向量
		_Int("Int",Int) = 344                 //整数
		_Float("Float",Float) = 25.0          //小数
		_Range("Range",Range(1,11))=6         //范围数只能是1-11 默认为6
		_2D("Texture",2D) = "white"{}         //得到图片,没有制定就为白色  
	    _Cube("Cube",Cube) = "white"{}            //立方体纹理
		_3D("Texture",3D) = "white"{}         //3D纹理
	}
		//SubShader可以有很多个,显卡运行效果的时候从第一个SubShader开始,如果第一个效果可以实现,使用第一个,如果存在一些的效果的实现不了,它会自动运行下一个SubShader
	SubShader
	{
		//pass,至少有一个,这里就是函数
		Pass
		{
                    //这里编写Shader代码 HLSLPROGRAM
                    CGPROGRAM
                    //使用CG语言编写Shader代码
                    
		    //分别获得上面的属性值
                    float4 _Color;     //half fixed  和float等价  float使用32位存储,half使用16位来存储 fixed是11位保存
                    float4 _Vector;
                    float _Int;
                    float _Float;
                    float _Range;
                    sampler2D _2D;
                    samplerCube _Cube;
                    sampler3D _3D;
				
                    ENDCG
        }
	}
	Fallback "VertexLit"      //如果全部不行,就执行这个shader,unity自己有的shader
}

在这里没有编写顶点着色器和片元的着色器,在下面的编写的过程中会完成,后面的编写的过程,主要是二个着色器的编写。

二:顶点着色器和片元着色器

js 复制代码
Shader "myshader/02 secondshader can run"
{
	SubShader
	{
		Pass
		{
			CGPROGRAM
			//顶点函数
                        #pragma vertex vert  //声明了定点的函数的函数名,名字为vert,从模型空间转换到剪裁空间的变化
			//片元函数
                        #pragma fragment frag  //声明了片元函数的函数名,名字为frag,返回模型中的每一个的像素值

			float4 vert(float4 v:POSITION) :SV_POSITION          //分别进行说明,通过语义告诉系统干嘛的,POSITION每一个MESH的顶点的数据,SV_POSITION是输出进行说明
			{
				float4 pos = UnityObjectToClipPos(v);          //实际上就是MVP矩阵,这里对于顶点坐标进行MVP变化 //mul(UNITY_MATRIX_MVP,v)
				return pos;
			}
			float4 frag() : SV_Target      //函数的实现
			{
				return float4(0.5,1,1,1);    //白色,前面为强制转换
			}
			ENDCG
            }
	}
	Fallback "VertexLit"
}

在顶点的着色器中,输入为float4 v:POSITION,输入的是每一个mesh中的顶点信息,:SV_POSITION 是对于顶点着色器的输出进行说明,这个坐标已经完成了MVP变化。float4 pos = UnityObjectToClipPos(v);是把输入的坐标进行MVP变换之后的坐标,完成了剪切计算,在计算了顶点的着色器之后,计算进入片元着色器,本例中没有片元着色器的输入变化。使用的相机为场景中的主相机。

三:使用结构体进行传送数据

在进行顶点着色器和片元着色器的过程中,可能需要传送大量不同的数据,一般还是使用结构体进行传送数据:

js 复制代码
Shader "myshader/03 Use struct"
{
	SubShader{
		Pass{
			CGPROGRAM
			//顶点函数
			#pragma vertex vert          
			//片元函数
			#pragma fragment frag       
		    
		    //使用结构体 application to vertex
			struct a2v {
				float4 vertex:POSITION;     //给与模型空间下的顶点坐标
				float3 normal:NORMAL;       //给予模型空间下的法线坐标
				float4 texcoord:TEXCOORD0;  //给予纹理坐标(第一套),这里使用的是float4,一般常用的UV是2个数据就可以使用,但是这里使用4个数据是为了插值使用
            };
	        //使用结构体 vertex to fragment
			struct v2f
			{
				float4 position:SV_POSITION;    //必须要返回位置
				float3 temp:COLOR0;            //颜色,必须要有语义
			};

			v2f vert(a2v v)
			{
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);
				f.temp = v.normal;
				return f;
			}

			float4 frag(v2f f) : SV_Target      
			{
				return float4(f.temp,1);    
			}
			ENDCG
		}
	}
	Fallback "VertexLit"
}

在本篇中分别使用了结构a2v,用来传递应用端到顶点着色器的数据,其中包含的信息有顶点信息,法线信息,纹理信息。在传送到片元着色器的过程中使用了结构体v2f,传送到片元的结构之中。

四:片元着色器的漫反射

这里来实现一下基本的漫反射的计算:

js 复制代码
Shader "Siki/04 Diffuse fragment"
{
	Properties
	{
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
	}
	SubShader
	{
		Pass
		{
				Tags{"LightMode" = "ForwardBase"}   //光照模型为前向渲染
			CGPROGRAM

#include "Lighting.cginc"       //第一个直射光(directional light)的颜色 _LightColor0  光的位置 _WorldSpaceLightPos0

		    //顶点函数
#pragma vertex vert          
			//片元函数
#pragma fragment frag       
			
			//获得属性值
			fixed4 _Diffuse;
			//使用结构体 application to vertex
			struct a2v 
			{
				float4 vertex:POSITION;     //给与模型空间下的顶点坐标
				float3 normal:NORMAL;       //法线
			};
			//使用结构体 vertex to fragment
			struct v2f
			{
				float4 position:SV_POSITION;    //必须要返回位置
				fixed3 worldNormalDir : COLOR;
			};
			v2f vert(a2v v)
			{
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);
				f.worldNormalDir = mul(v.normal, (float3x3) unity_WorldToObject);
				return f;
			}
			float4 frag(v2f f) : SV_Target
			{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;        //获得环境光
				fixed3 normalDir = normalize(f.worldNormalDir);    
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);                  //获得平行光的方向,由当前的顶点指向光源的方向
				fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, lightDir), 0);   //取得漫反射的颜色
				diffuse *= _Diffuse.rgb;                                                //乘上自己带有的颜色,颜色进行融合
				fixed3 tempColor = diffuse + ambient;
				return float4(tempColor,1);
			}
			ENDCG
        }
	}
	Fallback "VertexLit"
}

其中关于世界的法线的变化代码为:f.worldNormalDir = mul(v.normal, (float3x3) unity_WorldToObject);,需要先对于法线也进行世界空间的变化。在片元的着色器中有获得环境的光有:fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;然后获得世界光源的方向fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);,是当前的着色点指向的光源,然后计算漫反射的系数: fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, lightDir), 0);,最后计算得出总的光照的效果。

五:半程Lambert模型

js 复制代码
Shader "myshader/05 Diffuse fragment HalfLambert"
{
	Properties
	{
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
	}
	SubShader
	{
		Pass
		{
			Tags{"LightMode" = "ForwardBase"}   //光照模型为前向渲染
			CGPROGRAM

#include "Lighting.cginc"       //第一个直射光(directional light)的颜色 _LightColor0  光的位置 _WorldSpaceLightPos0

		//顶点函数
#pragma vertex vert          
			//片元函数
#pragma fragment frag       
			
			//获得属性值
			fixed4 _Diffuse;
			//使用结构体 application to vertex
			struct a2v 
			{
				float4 vertex:POSITION;     //给与模型空间下的顶点坐标
				float3 normal:NORMAL;       //法线
			};
			//使用结构体 vertex to fragment
			struct v2f
			{
				float4 position:SV_POSITION;    //必须要返回位置
				fixed3 worldNormalDir : COLOR;
			};
			v2f vert(a2v v)
			{
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);
				f.worldNormalDir = mul(v.normal, (float3x3) unity_WorldToObject);
				return f;
			}

			float4 frag(v2f f) : SV_Target
			{
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;        //获得环境光

				fixed3 normalDir = normalize(f.worldNormalDir);    
				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);        //获得平行光的方向,由当前的顶点指向光源的方向
				float halfLambert = max(dot(normalDir, lightDir), 0)*0.5f+0.5f;
				fixed3 diffuse = _LightColor0.rgb * halfLambert;   //取得漫反射的颜色
				diffuse *= _Diffuse.rgb;                   //乘上自己带有的颜色,颜色进行融合
				fixed3 tempColor = diffuse + ambient;
				return float4(tempColor,1);
			}
			ENDCG
        }
	}
	Fallback "VertexLit"
}

相比于上一章节,本章主要采用的漫反射的优化过程,float halfLambert = max(dot(normalDir, lightDir), 0)*0.5f+0.5f;能够优化漫反射的效果。

六:片元的高光反射

在计算了漫反射之后,现在来计算高光反射的效果

js 复制代码
Shader "myshader/06-Specular Fragment"
{
	Properties
	{
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
		_Specular("Specular Color",Color) = (1,1,1,1)
		_Gloss("Gloss",Range(8,200)) = 10

	}
	SubShader
	{
		Pass
		{
			Tags{ "LightMode" = "ForwardBase" }
			CGPROGRAM
			#include "Lighting.cginc" //取得第一个直射光的颜色 _LightColor0 第一个直射光的位置_WorldSpaceLightPos0 
			#pragma vertex vert
			#pragma fragment frag
			fixed4 _Diffuse;    //分别获得前面定义的数据,漫反射颜色
			fixed4 _Specular;   //高光颜色
			half _Gloss;        //光泽度
			//application to vertex
			struct a2v 
			{
				float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
				float3 normal:NORMAL;
			};
			struct v2f {
				float4 position:SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldVertex :TEXCOORD1;
			};
			v2f vert(a2v v) 
			{
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);
				f.worldNormal = mul(v.normal, (float3x3) unity_WorldToObject);
				f.worldVertex = mul(v.vertex, unity_WorldToObject).xyz;
				return f;
			}
			fixed4 frag(v2f f) :SV_Target{

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

				fixed3 normalDir = normalize(f.worldNormal);

				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说 光的位置就是光的方向 ,因为光是平行光

				fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, lightDir), 0) * _Diffuse.rgb;  //取得漫反射的颜色

				fixed3 reflectDir = normalize(reflect(-lightDir, normalDir));

				fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - f.worldVertex);

				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(reflectDir, viewDir), 0), _Gloss);

				fixed3 tempColor = diffuse + ambient + specular;

				return fixed4(tempColor,1);
			}

			ENDCG
		}
	}
	Fallback "Diffuse"
}

v2f的结构体中包含了顶点信息和法线的信息,在顶点的着色器中都需要进行模型变化,f.worldNormal = mul(v.normal, (float3x3) unity_WorldToObject); f.worldVertex = mul(v.vertex, unity_WorldToObject).xyz;然后再片元的着色器中计算高光的反射的部分: fixed3 reflectDir = normalize(reflect(-lightDir, normalDir)); fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - f.worldVertex); fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(reflectDir, viewDir), 0), _Gloss); 首先进行计算高光的反射的光线的法相,reflect输入的是一个方向是入射方向到片元。然后计算高光的反射的光线:fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(reflectDir, viewDir), 0), _Gloss);,然后把所有的结果进行相加。

六:片元的blinn-pong模型

js 复制代码
Shader "Siki/09-Specular Fragment BlinnPhong"{
	Properties
	{
		_Diffuse("Diffuse Color",Color) = (1,1,1,1)
		_Specular("Specular Color",Color) = (1,1,1,1)
		_Gloss("Gloss",Range(8,200)) = 10

	}
	SubShader
	{
		Pass{
			Tags{ "LightMode" = "ForwardBase" }
			CGPROGRAM
			#include "Lighting.cginc" //取得第一个直射光的颜色 _LightColor0 第一个直射光的位置_WorldSpaceLightPos0 
			#pragma vertex vert
			#pragma fragment frag
			fixed4 _Diffuse;
			fixed4 _Specular;
			half _Gloss;
			//application to vertex
			struct a2v 
			{
				float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
				float3 normal:NORMAL;
			};
			struct v2f 
			{
				float4 position:SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float4 worldVertex :TEXCOORD1;
			};

			v2f vert(a2v v) 
			{
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);
				//f.worldNormal = mul(v.normal, (float3x3) _World2Object);
				f.worldNormal = UnityObjectToWorldNormal(v.normal);
				f.worldVertex = mul(v.vertex, unity_WorldToObject);
				return f;
			}

			fixed4 frag(v2f f) :SV_Target
			{

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

				fixed3 normalDir = normalize(f.worldNormal);

				//fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);//对于每个顶点来说 光的位置就是光的方向 ,因为光是平行光
				fixed3 lightDir = normalize(WorldSpaceLightDir(f.worldVertex).xyz);

				fixed3 diffuse = _LightColor0.rgb * max(dot(normalDir, lightDir), 0) * _Diffuse.rgb;  //取得漫反射的颜色

				//fixed3 reflectDir = normalize(reflect(-lightDir, normalDir)); 

				//fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - f.worldVertex );
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldVertex));

				fixed3 halfDir = normalize(viewDir + lightDir);

				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(normalDir, halfDir), 0), _Gloss);

				fixed3 tempColor = diffuse + ambient + specular;

				return fixed4(tempColor,1);
			}

			ENDCG
		}
	}
	Fallback "Diffuse"
}

在片元的着色器中

八:带有纹理的模型

js 复制代码
Shader "myshader/8-Texture"{
	Properties
	{
		//_Diffuse("Diffuse Color",Color) = (1,1,1,1)
		_Color("Color",Color) = (1,1,1,1)
		_MainTex("Main Tex",2D) = "white"{}
		_Specular("Specular Color",Color) = (1,1,1,1)
		_Gloss("Gloss",Range(10,200)) = 20
	}
	SubShader
	{
		Pass{
			Tags{"LightMode" = "ForwardBase"}
			CGPROGRAM
			#include "Lighting.cginc"
			#pragma vertex vert
			#pragma fragment frag
			//fixed4 _Diffuse;
			fixed4 _Color;
			sampler2D _MainTex;       //纹理
			float4 _MainTex_ST;       //获得缩放和偏移
			fixed4 _Specular;  
			half _Gloss;
			struct a2v 
			{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
				float4 texcoord:TEXCOORD0;
			};
			struct v2f 
			{
				float4 svPos:SV_POSITION;
				float3 worldNormal:TEXCOORD0;
				float4 worldVertex:TEXCOORD1;
				float2 uv:TEXCOORD2;
			};
			v2f vert(a2v v) 
			{
				v2f f;
				f.svPos = UnityObjectToClipPos(v.vertex);
				f.worldNormal = UnityObjectToWorldNormal(v.normal);
				f.worldVertex = mul(v.vertex, unity_WorldToObject);
				f.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;    //更改这里的UV坐标
				return f;
			}
			fixed4 frag(v2f f) :SV_Target
			{
				fixed3 normalDir = normalize(f.worldNormal);

				fixed3 lightDir = normalize(WorldSpaceLightDir(f.worldVertex));

				fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb;

				fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(normalDir, lightDir), 0);

				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldVertex));

				fixed3 halfDir = normalize(lightDir + viewDir);

				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(dot(normalDir, halfDir), 0), _Gloss);

				fixed3 tempColor = diffuse + specular + UNITY_LIGHTMODEL_AMBIENT.rgb * texColor;

				return fixed4(tempColor, 1);

			}

			ENDCG
		}
	}
	Fallback "Specular"
}

九:更改带有法线的效果

js 复制代码
Shader "Siki/13-Rock Normal Map"
{
	Properties
	{
		//_Diffuse("Diffuse Color",Color) = (1,1,1,1)
		_Color("Color",Color) = (1,1,1,1)
		_MainTex("Main Tex",2D) = "white"{}
		_NormalMap("Normal Map",2D) = "bump"{}
		_BumpScale("Bump Scale",Float) = 1
	}
	SubShader
	{
		Pass
		{
			Tags{ "LightMode" = "ForwardBase" }
			CGPROGRAM
			#include "Lighting.cginc"
			#pragma vertex vert
			#pragma fragment frag

			//fixed4 _Diffuse;
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _NormalMap;
			float4 _NormalMap_ST;
			float _BumpScale;

			struct a2v 
			{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
				float4 tangent:TANGENT;//tangent.w是用来确定切线空间中坐标轴的方向的 
				float4 texcoord:TEXCOORD0;
			};
			struct v2f 
			{
				float4 svPos:SV_POSITION;
				//float3 worldNormal:TEXCOORD0;
				//float4 worldVertex:TEXCOORD1;
				float3 lightDir : TEXCOORD0;
				float4 uv:TEXCOORD1;
			};

			v2f vert(a2v v) 
			{
				v2f f;
				f.svPos = UnityObjectToClipPos(v.vertex);
				//	f.worldNormal = UnityObjectToWorldNormal(v.normal);
				//	f.worldVertex = mul(v.vertex, _World2Object);
				f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw;
				TANGENT_SPACE_ROTATION;//调用这个后之后,会得到一个矩阵 rotation 这个矩阵用来把模型空间下的方向转换成切线空间下
				//ObjSpaceLightDir(v.vertex)//得到模型空间下的平行光方向 
				f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));
				return f;
			}
			fixed4 frag(v2f f) :SV_Target
			{

				//fixed3 normalDir = normalize(f.worldNormal);
				fixed4 normalColor = tex2D(_NormalMap,f.uv.zw);
				//	fixed3 tangentNormal = normalize(  normalColor.xyz * 2 - 1 ) ; //切线空间下的法线
				fixed3 tangentNormal = UnpackNormal(normalColor);
				tangentNormal.xy = tangentNormal.xy * _BumpScale;
				tangentNormal = normalize(tangentNormal);

				fixed3 lightDir = normalize(f.lightDir);

				fixed3 texColor = tex2D(_MainTex, f.uv.xy) * _Color.rgb;

				fixed3 diffuse = _LightColor0.rgb * texColor * max(dot(tangentNormal, lightDir), 0);

				fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rgb * texColor;

				return fixed4(tempColor, 1);

			}
			ENDCG
		}
	}
	Fallback "Specular"
}

十:包含透明的渲染

js 复制代码
Shader "Siki/14-Rock Alpha"
{
	Properties
	{
		//_Diffuse("Diffuse Color",Color) = (1,1,1,1)
		_Color("Color",Color) = (1,1,1,1)
		_MainTex("Main Tex",2D) = "white"{}
		_NormalMap("Normal Map",2D) = "bump"{}
		_BumpScale("Bump Scale",Float) = 1
		_AlphaScale("Alpha Scale",Float) = 1
	}
	SubShader
	{
		Tags{ "Queue" = "Transparent" "IngnoreProjector" = "True" "RenderType" = "Transparent" }     //渲染队列,该着色器是透明着色器,是否忽略投影,渲染的方式
		Pass
		{
			Tags{ "LightMode" = "ForwardBase" }

			ZWrite Off                                 //关闭深度写入
			Blend SrcAlpha OneMinusSrcAlpha            //混合分别为 a,1-a

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

			//fixed4 _Diffuse;
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _NormalMap;
			float4 _NormalMap_ST;
			float _BumpScale;
			float _AlphaScale;

			struct a2v 
			{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
				float4 tangent:TANGENT;//tangent.w是用来确定切线空间中坐标轴的方向的 
				float4 texcoord:TEXCOORD0;
			};
			struct v2f 
			{
				float4 svPos:SV_POSITION;
				//float3 worldNormal:TEXCOORD0;
				//float4 worldVertex:TEXCOORD1;
				float3 lightDir : TEXCOORD0;
				float4 uv:TEXCOORD1;
			};

			v2f vert(a2v v) 
			{
				v2f f;
				f.svPos = UnityObjectToClipPos(v.vertex);
				//	f.worldNormal = UnityObjectToWorldNormal(v.normal);
				//	f.worldVertex = mul(v.vertex, _World2Object);
				f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				f.uv.zw = v.texcoord.xy * _NormalMap_ST.xy + _NormalMap_ST.zw;

				TANGENT_SPACE_ROTATION;//调用这个后之后,会得到一个矩阵 rotation 这个矩阵用来把模型空间下的方向转换成切线空间下

				//ObjSpaceLightDir(v.vertex)//得到模型空间下的平行光方向 
				f.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex));

				return f;
			}
			fixed4 frag(v2f f) :SV_Target
			{

				//fixed3 normalDir = normalize(f.worldNormal);
				fixed4 normalColor = tex2D(_NormalMap,f.uv.zw);
				//	fixed3 tangentNormal = normalize(  normalColor.xyz * 2 - 1 ) ; //切线空间下的法线
				fixed3 tangentNormal = UnpackNormal(normalColor);
				tangentNormal.xy = tangentNormal.xy * _BumpScale;
				tangentNormal = normalize(tangentNormal);

				fixed3 lightDir = normalize(f.lightDir);

				fixed4 texColor = tex2D(_MainTex, f.uv.xy) * _Color;
				
				fixed3 diffuse = _LightColor0.rgb * texColor.rgb * max(dot(tangentNormal, lightDir), 0);
	
				fixed3 tempColor = diffuse + UNITY_LIGHTMODEL_AMBIENT.rgb * texColor;

				//return fixed4(tempColor,_AlphaScale * texColor.a);     //这个的a的值为0
				return fixed4(tempColor,0.5);
			}
			ENDCG
		}
	}
	Fallback "Specular"
}

这些是常用的unity的自带管线的编写,一般使用URP的管线的更多。

相关推荐
Thomas_YXQ4 天前
Unity3D Shader的阴影部分法线效果详解
开发语言·游戏·unity·架构·unity3d
氦客4 天前
Unity3D入门(四) : Android和Unity3D交互 - Unity调用Android
android·unity·交互·unity3d·调用·javaobject·javaclass
Thomas_YXQ7 天前
Unity3D PostLateUpdate为何突然占用大量时间详解
开发语言·数码相机·游戏·unity·架构·unity3d
Thomas_YXQ8 天前
Unity3D 中构建行为树插件详解
游戏·unity·架构·unity3d·游戏开发
随遇而安的生活12 天前
Unity android 接USBCamera
android·unity3d
留待舞人归13 天前
【Unity杂谈】iOS 18中文字体显示问题的调查
游戏·unity·ios·游戏引擎·unity3d
吾名招财14 天前
unity3d入门教程八-飞机大战
游戏引擎·unity3d
吾名招财20 天前
unity3d入门教程五
游戏引擎·unity3d
吾名招财20 天前
unity3d入门教程六
游戏引擎·unity3d
吾名招财20 天前
unity3d入门教程七
游戏引擎·unity3d