Unity_Shader

Shader基础

shader

Shader的名字会直接决定shader在material里出现的路径

SubShader 顶点函数与片元函数通信

Shader "LiHao/Shader03"{
	SubShader{
		Pass{
			CGPROGRAM
			
#pragma vertex vert		
#pragma fragment frag

			struct a2v{
				float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
				float3 normal:NORMAL;//告诉unity把模型空间下的法线方向填充给normal
				float4 texcoord:TEXCOORD0;//告诉unity把第一套纹理坐标填充给texcoord
			};
			struct v2f{
				float4 position:SV_POSITION;
				float3 temp:COLOR0;
			};

			v2f vert(a2v v){
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);
				f.temp = v.normal;
				return f;
			
			}
			
			fixed4 frag(v2f f) :SV_Target{
				return fixed4(f.temp, 1);
			}
			ENDCG
		}
	}
	Fallback "VertexLit"
}

Unity Shader语义

1、从应用阶段传递模型数据给顶点着色器时的语义表如下:

语义描述
POSITION模型空间中的顶点坐标 通常float4
NORMAL模型空间中的顶点法线 通常float3
TANGENT模型空间中的顶点切线 通常 float4
TEXCOORD(n)模型空间中的顶点的纹理坐标 n组
COLOR模型空间中的顶点颜色 通常fixed4 float4

2、从顶点着色器传递到片元着色器时支持的语义表如下:

语义描述
SV_POSITION剪裁空间中的顶点坐标
COLOR0通常用于输出第一组顶点颜色,不是必须
COLOR1通常用于输出第二组顶点颜色,不是必须
TEXCOORDN(0~7)通常用于输出第n组纹理坐标,不是必须

 

 

 

3、片元着色器输出时支持的语义:

语义描述
SV_Target输出值将会存储到渲染目标中











 

 

什么是光照模型

光照模型就是一个公式,使用这个公式来计算在某个点的光照效果

标准光照模型

在标准光照模型里面,我们把进入摄像机的光分为下面四个部分

自发光(emissive) 
高光反射(specular)Specular=直射光颜色*pow(max(cosθ,0),10)   注:θ:是反射光方向和视野方向的夹角
漫反射 (diffuse)Diffuse=直射光颜色*max(0,cos夹角(光和法线的夹角))
环境光 (ambient) 

 

 

 

 

 

Tags{"LightMode"="ForwardBase"}只有定义了正确的LightMode才能得到Unity内置的光照变量
#include "Lighting.cginc"包含unity的内置的文件,才可以使用unity内置的一些变量
normalize()用来把一个向量,单位化(原来方向保持不变,长度变为1)
max()用来取得函数中最大的一个
dot()用来取得两个向量的点积
_WorldSpaceLightPos0取得平行光的位置
_LightColor0取得平行光的颜色
UNITY_MATRIX_MVP这个矩阵用来把一个坐标从模型空间 转换到剪裁空间
_World2Object这个矩阵用来把一个方向从世界空间转换到模型空间

 

 

 

 

 

 

 

 

 

逐顶点漫反射实例:

Shader "LiHao/04_Diffuse_Vertex"{
	Properties{
		_Diffuse("Diffuse Color", Color) = (1,1,1,1)
	}
	SubShader{
		Pass{
			Tags{ "LightMode" = "ForwardBase" }
			CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert		
#pragma fragment frag
			fixed4 _Diffuse;
			struct a2v{
				float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
				float3 normal:NORMAL;//告诉unity把模型空间下的法线方向填充给normal
				
			};
			struct v2f{
				float4 position:SV_POSITION;
				float3 color:COLOR;
			};

			v2f vert(a2v v){
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

				fixed3 normalDir = normalize(mul(v.normal, (float3x3)_World2Object));

				fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

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

				f.color = diffuse+ambient;
				return f;
			
			}
			
			fixed4 frag(v2f f) :SV_Target{
				return fixed4(f.color, 1);
			}
			ENDCG
		}
	}
	Fallback "VertexLit"
}

逐像素漫反射示例:

Shader "LiHao/05_Diffuse_Fragment"{
	Properties{
		_Diffuse("Diffuse Color", Color) = (1,1,1,1)
	}
	SubShader{
		Pass{
			Tags{ "LightMode" = "ForwardBase" }
			CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert		
#pragma fragment frag
			fixed4 _Diffuse;
			struct a2v{
				float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
				float3 normal:NORMAL;//告诉unity把模型空间下的法线方向填充给normal
				
			};
			struct v2f{
				float4 position:SV_POSITION;
				//float3 color:COLOR;
				float3 worldNormalDir:COLOR;
			};

			v2f vert(a2v v){
				v2f f;
				f.position = mul(UNITY_MATRIX_MVP, v.vertex);
				f.worldNormalDir = mul(v.normal, (float3x3)_World2Object);
				
				return f;
			
			}
			
			fixed4 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.rgb;

				float3 diffTemp = diffuse + ambient;

				return fixed4(diffTemp, 1);
			}
			ENDCG
		}
	}
	Fallback "VertexLit"
}

逐顶点与逐像素漫反射对比

高光反射

逐顶点高光反射:

Shader "LiHao/07_Specular_Vertex"{
	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"
#pragma vertex vert		
#pragma fragment frag
				fixed4 _Diffuse;
				fixed4 _Specular;
				half _Gloss;
				struct a2v{
					float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
					float3 normal:NORMAL;//告诉unity把模型空间下的法线方向填充给normal

				};
				struct v2f{
					float4 position:SV_POSITION;
					float3 color:COLOR;
				};

				v2f vert(a2v v){
					v2f f;
					f.position = mul(UNITY_MATRIX_MVP, v.vertex);

					fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

					fixed3 normalDir = normalize(mul(v.normal, (float3x3)_World2Object));

					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 - mul(v.vertex, _World2Object));

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

					f.color = diffuse + ambient + specular;
					return f;

				}

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

逐像素高光反射:

Shader "LiHao/08_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"
#pragma vertex vert		
#pragma fragment frag
				fixed4 _Diffuse;
				fixed4 _Specular;
				half _Gloss;
				struct a2v{
					float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
					float3 normal:NORMAL;//告诉unity把模型空间下的法线方向填充给normal

				};
				struct v2f{
					float4 position:SV_POSITION;
					float3 worldNormal:TEXCOORD0;
					float3 worldVertex:TEXCOORD1;
				};

				v2f vert(a2v v){
					v2f f;
					f.position = mul(UNITY_MATRIX_MVP, v.vertex);
					f.worldNormal = mul(v.normal, (float3x3)_World2Object);
					f.worldVertex = mul(v.vertex, _World2Object);
					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*pow(max(dot(reflectDir, viewDir), 0), _Gloss);

					fixed3 tempColor = diffuse + ambient + specular;

					return fixed4(tempColor, 1);
				}
					ENDCG
			}
		}
		Fallback "VertexLit"
}

逐顶点与逐像素高光反射对比:

Blinn-Phong 高光反射模型

这种光照模型的高光反射看起来更大,更亮一些。在实际渲染中,绝大多数情况会选择 Blinn-Phong 光照模型,此种光照模型更符合实验结果

与普通高光反射对比:

Shader "LiHao/09_Specular_Fragment_Blinn-Phong-unity"{
	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" }		//定义该Pass在Unity流水线中用于前向渲染
				CGPROGRAM								//与ENDCG配对用于包裹Cg代码片
#include "Lighting.cginc"								//引入内置文件
#pragma vertex vert										//利用#pragma告诉Unity顶点着色器的名字叫vert
#pragma fragment frag									//利用#pragma告诉Unity片元着色器的名字叫frag
				fixed4 _Diffuse;						//定义于Properties中相匹配的变量
				fixed4 _Specular;
				half _Gloss;
				struct a2v{								//顶点着色器的输入结构体
					float4 vertex:POSITION;//告诉unity把模型空间下的顶点坐标填充给vertex
					float3 normal:NORMAL;//告诉unity把模型空间下的法线方向填充给normal

				};
				struct v2f{								//顶点着色器的输出结构体和片元着色器的输入结构体
					float4 position:SV_POSITION;		//模型的顶点信息(基于剪裁空间)
					float3 worldNormal:TEXCOORD0;		//模型的法线信息(基于世界空间)
					float4 worldVertex:TEXCOORD1;		//模型的顶点信息(基于世界空间)
				};

				v2f vert(a2v v){
					v2f f;
					f.position = mul(UNITY_MATRIX_MVP, v.vertex);	//顶点位置信息从模型空间转换到剪裁空间
					//f.worldNormal = mul(v.normal, (float3x3)_World2Object);
					f.worldNormal = UnityObjectToWorldNormal(v.normal);	//模型坐标的法线信息从模型空间转换到世界空间
					f.worldVertex = mul(v.vertex, _World2Object);	//模型坐标的顶点信息从模型空间转换到世界空间
					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 ligthDir = normalize(WorldSpaceLightDir(f.worldVertex).xyz);	//光照方向

					fixed3 diffuse = _LightColor0.rgb*max(dot(normalDir, ligthDir), 0)*_Diffuse.rgb;	//漫反射

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

					//fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - f.worldVertex);
					fixed3 viewDir = normalize(UnityWorldSpaceViewDir(f.worldVertex).xyz);	//视角方向

					fixed3 halfDir = normalize(viewDir + ligthDir);	// Blinn-Phong 光照模型计算

					fixed3 specular = _LightColor0.rgb*_Specular*pow(max(dot(normalDir, halfDir), 0), _Gloss);	//高光反射

					fixed3 tempColor = diffuse + ambient + specular;

					return fixed4(tempColor, 1);
				}
					ENDCG
			}
		}
		Fallback "VertexLit"
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值