读一读

Shader "chicai/7"{
	Properties{
		_Specular("Specular",Color)=(1,1,1,1)
		_Glass("Glass",Range(8,20))=8
		_MainTex("MainTex",2D)="white"{}
		_NormalTex("NormalTex",2D)="white"{}
		_NormalIndexd("AoTuQiangDu",float)=1
	}

	SubShader{
		Pass{
			Tags{"RenderMode"="ForwardBase"}

			CGPROGRAM
			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Glass;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _NormalTex;
			float4 _NormalTex_ST;
			float _NormalIndexd;

			#include "Lighting.cginc"
			#pragma vertex vert
			#pragma fragment frag
			struct a2v{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
				float4 tangent:TANGENT;
				float4 texcoord:TEXCOORD0;
			};

			struct v2f{
				float4 position:SV_POSITION;
				fixed3 nor:COLOR0;
				fixed3 lightDir:COLOR1;
				fixed3 viewDir:COLOR2;
				float4 uv:TEXCOORD0;
			};

			v2f vert(a2v v){
				v2f f;
				f.position = UnityObjectToClipPos(v.vertex);
				f.nor = normalize(mul(unity_ObjectToWorld,v.normal));

				TANGENT_SPACE_ROTATION;
				f.lightDir = normalize(mul(rotation,ObjSpaceLightDir(v.vertex))).xyz;
				f.viewDir = normalize(mul(rotation,ObjSpaceViewDir(v.vertex))).xyz;
				f.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				f.uv.zw = v.texcoord.xy * _NormalTex_ST.xy + _NormalTex_ST.zw;
				return f;
			}

			fixed4 frag(v2f f):SV_Target{

				fixed3 tangentNormal = UnpackNormal(tex2D(_NormalTex,f.uv.wz));
				tangentNormal.xy = tangentNormal.xy * _NormalIndexd;
				tangentNormal = normalize(tangentNormal);

				fixed3 texCol = tex2D(_MainTex,f.uv);//计算改uv上贴图的颜色,当物体本身颜色——Diffuse
				fixed3 diffuseCol = _LightColor0.rgb * texCol  * (dot(tangentNormal,f.lightDir)/2+0.5);

				fixed3 aveDir = normalize(f.lightDir+f.viewDir);
				fixed3 specularCol = _LightColor0.rgb * _Specular * pow(max(dot(aveDir,tangentNormal),0),_Glass);

				fixed3 allColor = diffuseCol + specularCol;

				return fixed4(allColor,1);
			}

			ENDCG
		}
	}
}



Unity属性中添加法线贴图属性和凹凸强度系数

_NormalTex("NormalTex",2D)="white"{}
_NormalIndexd("AoTuQiangDu",float)=1

CG声明对应的变量和平移缩放变量

sampler2D _NormalTex;
float4 _NormalTex_ST;
float _NormalIndexd;

引进切线到顶点函数float4 tangent:TANGENT;

使用传入片元的uv参数的xy传递贴图uv坐标,zw传递法线贴图的uv坐标

f.uv.zw = v.texcoord.xy * _NormalTex_ST.xy + _NormalTex_ST.zw;

转变视野方向和光线方向到切线空间

TANGENT_SPACE_ROTATION;//一个宏,计算出rotation
f.lightDir = normalize(mul(rotation,ObjSpaceLightDir(v.vertex))).xyz;
f.viewDir = normalize(mul(rotation,ObjSpaceViewDir(v.vertex))).xyz;

片元中得出相应的法线

fixed3 tangentNormal = UnpackNormal(tex2D(_NormalTex,f.uv.wz));//像素图片(0-255)转化为方向的(-1,1)
tangentNormal.xy = tangentNormal.xy * _NormalIndexd;
tangentNormal = normalize(tangentNormal);

Shader "chicai/6"{
	Properties{
		_Specular("Specular",Color)=(1,1,1,1)
		_Glass("Glass",Range(8,20))=8
		_MainTex("MainTex",2D)="white"{}
	}

	SubShader{
		Pass{
			Tags{"RenderMode"="ForwardBase"}

			CGPROGRAM
			fixed4 _Diffuse;
			fixed4 _Specular;
			float _Glass;
			sampler2D _MainTex;
			float4 _MainTex_ST;

			#include "Lighting.cginc"
			#pragma vertex vert
			#pragma fragment frag
			struct a2v{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
				float4 texcoord:TEXCOORD0;
			};

			struct v2f{
				float4 position:SV_POSITION;
				fixed3 nor:COLOR0;
				fixed3 lightDir:COLOR1;
				fixed3 viewDir:COLOR2;
				float2 uv:TEXCOORD0;
			};

			v2f vert(a2v o){
				v2f f;
				f.position = UnityObjectToClipPos(o.vertex);
				f.nor = normalize(mul(unity_ObjectToWorld,o.normal));
				f.lightDir = normalize(WorldSpaceLightDir(o.vertex));
				f.viewDir = normalize(WorldSpaceViewDir(o.vertex));
				f.uv = o.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				return f;
			}

			fixed4 frag(v2f f):SV_Target{

				fixed3 texCol = tex2D(_MainTex,f.uv);//计算该uv上贴图的颜色,当物体本身颜色——Diffuse
				fixed3 diffuseCol = _LightColor0.rgb * texCol  * (dot(f.nor,f.lightDir)/2+0.5);

				fixed3 aveDir = normalize(f.lightDir+f.viewDir);//光照方向和视野方向的平分线
				fixed3 specularCol = _LightColor0.rgb * _Specular * pow(max(dot(aveDir,f.nor),0),_Glass);

				fixed3 allColor = diffuseCol + specularCol;

				return fixed4(allColor,1);
			}

			ENDCG
		}
	}
}

首先,Unity变量:

_MainTex("MainTex",2D)="white"{}


对应CG变量:

sampler2D _MainTex;
float4 _MainTex_ST;//固定,变量名_ST,xy分量表示贴图的缩放,zw分量表示贴图的偏移


顶点函数传入uv纹理坐标  float4 texcoord:TEXCOORD0;


计算出含偏移缩放等的纹理坐标给片元

float2 uv:TEXCOORD0;
f.uv = o.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;//乘缩放,+偏移
f.uv = TRANSFORM_TEX(v.texcoord, _MainTex_ST);//内置的方法转换uv,等同于上面一行


找出对应uv坐标对应的纹理颜色充当漫反射自身颜色


// 摄像机方向(视角方向)
float3 WorldSpaceViewDir(float4 v)      // 根据模型空间中的顶点坐标 得到 (世界空间)从这个点到摄像机的观察方向
float3 UnityWorldSpaceViewDir(float4 v) // 世界空间中的顶点坐标==》世界空间从这个点到摄像机的观察方向
float3 ObjSpaceViewDir(float4 v)        // 模型空间中的顶点坐标==》模型空间从这个点到摄像机的观察方向

// 光源方向
float3 WorldSpaceLightDir(float4 v)      // 模型空间中的顶点坐标==》世界空间中从这个点到光源的方向
float3 UnityWorldSpaceLightDir(float4 v) // 世界空间中的顶点坐标==》世界空间中从这个点到光源的方向
float3 ObjSpaceLightDir(float4 v)        // 模型空间中的顶点坐标==》模型空间中从这个点到光源的方向

// 方向转换
float3 UnityObjectToWorldNormal(float3 norm) // 把法线方向 模型空间==》世界空间
float3 UnityObjectToWorldDir(float3 dir)     // 把方向 模型空间=》世界空间
float3 UnityWorldToObjectDir(float3 dir)     // 把方向 世界空间=》模型空间


666.png


公式:Specular = 直射光 * pow( max(cosβ,0) ,范围系数)

β角指的是法线和x的夹角,x指的是直射光和视野方向的平分线

公式的改变就只有夹角不同,这个效果的反光范围会比较大

QQ图片20171227101246.png


//计算高光
fixed3 reflectDir = normalize( reflect(-lightDir,normalDir) );
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld,v.vertex));
fixed3 specularColor = _LightColor0.rgb * _Specular * (pow( max( dot(reflectDir,viewDir) ,0),_Gloss) );

f.color = diffuseColor + specularColor;

主要计算两个方向,反射光的方向和视野方向

_Specular是自定义属性,为高光颜色

反射光方向主要用reflect()方法得到,两个参数为入射光的方向和法线

视野方向用摄像机位置-点的位置来得到。


公式:specular = 直射光 * pow( max(cosβ,0) ,范围系数)

β角指的是反射光的方向和该点到相机(视野)方向的夹角。

QQ图片20171226111217.png


使用兰伯特光照模型计算的模型背面颜色都是全黑色这样子不好。所有演变了一个半兰伯特模型

公式:diffuse = 直射光颜色 * ( cosβ * 0.5 + 0.5)

cosβ的范围为[-1,1],乘于0.5后为[-0.5,0.5],在加上0.5后就变成[0,1]了,刚好满足颜色的范围。


颜色之间相乘,表示融合两种颜色

颜色之间相加,表示加强