一.逐顶点高光反射
在原来漫反射的基础上增加了高光,以及加入两个参数调节高光的范围以及颜色
PS: reflect(I, N)
根据入射光方向向量 I,和顶点法向量N,计算反射光方向向量。其中I和N 必须被归一化,需要非常注意的是,这个I 是指向顶点的;函数只对三元向量有效。
Shader "Custom/vertex specular"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
//通过参数调整高光的范围和颜色
_Gloss("Gloss ",Range(0,20))=5
_Color("Color", COLOR )=(1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
fixed3 color:COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//为什么要用half:关于一些性能上的考虑,尽量使用低精度的浮点数
//浮点数精度相关:fixed<half<float
half _Gloss;
fixed4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//o.uv = TRANSFORM_TEX(v.uv, _MainTex);
//环境光的颜色
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;
//模型空间转换到世界空间
fixed3 normalDir=normalize( mul(unity_ObjectToWorld,v.normal));
//取到世界空间下平行光的位置
fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
//漫反射 ; _LightColor0.rgb:取得第一个平行光的颜色
fixed3 diffuse=_LightColor0.rgb * max(0,dot(normalDir,lightDir));
//反射光的方向
fixed3 reflectDir = reflect (-lightDir,normalDir);
//相机的位置减去顶点的位置,顶点要先从模型空间转换到世界空间
fixed3 viewDir = normalize ( _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld,v.vertex).xyz ) ;
//高光
fixed3 specular =_LightColor0.rgb * pow ( max ( 0,dot( reflectDir,viewDir )) ,_Gloss ) * _Color;
o.color=diffuse + ambient + specular ;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.color,1);
}
ENDCG
}
}
}
二. 逐像素高光反射
Shader "Custom/fragment specular"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
//通过参数调整高光的范围和颜色
_Gloss("Gloss ",Range(0,20))=5
_Color("Color", COLOR )=(1,1,1,1)
}
SubShader
{
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
fixed3 color:COLOR;
//其实TEXCOORD0也可以存储法线向量。。
//不能有相同的纹理坐标
float3 worldNormalDir:TEXCOORD1;
float3 worldVertex:TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
//为什么要用half:关于一些性能上的考虑,尽量使用低精度的浮点数
//浮点数精度相关:fixed<half<float
half _Gloss;
fixed4 _Color;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldNormalDir=normalize( mul(unity_ObjectToWorld,v.normal));
o.worldVertex=mul(unity_ObjectToWorld,v.vertex).xyz;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 normalDir=normalize(i.worldNormalDir);
//环境光的颜色
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;
//取到世界空间下平行光的位置
fixed3 lightDir=normalize(_WorldSpaceLightPos0.xyz);
//漫反射 ; _LightColor0.rgb:取得第一个平行光的颜色
fixed3 diffuse=_LightColor0.rgb * max(0,dot(normalDir,lightDir));
//反射光的方向
fixed3 reflectDir = reflect (-lightDir,normalDir);
//相机的位置减去顶点的位置,顶点要先从模型空间转换到世界空间
fixed3 viewDir = normalize ( _WorldSpaceCameraPos.xyz - i.worldVertex) ;
//高光
fixed3 specular =_LightColor0.rgb * pow ( max ( 0,dot( reflectDir,viewDir )) ,_Gloss ) * _Color;
fixed3 tempColor=diffuse=diffuse + ambient + specular ;
return fixed4(tempColor,1);
}
ENDCG
}
}
}
************Blinn光照模型和Blinn-Phong 光照模型 ************
Blinn光照模型:Specular =平行光 * pow ( max ( 0 , cosθ) , 参数x )
Blinn-Phong光照模型:Specular =平行光 * pow ( max ( 0 , cosθ) , 参数x )
(θ为平行光与视野方向夹角的平分线与法线的夹角)
代码修改:
fixed3 reflectDir = reflect (-lightDir,normalDir);
fixed3 specular =_LightColor0.rgb * pow ( max ( 0,dot( reflectDir,viewDir )) ,_Gloss ) * _Color;
//获得平分线的向量
fixed3 halfDir = normalize( lightDir + viewDir );
fixed3 specular =_LightColor0.rgb * pow ( max ( 0,dot( normalDir,halfDir )) ,_Gloss ) * _Color;
区别:Blinn-Phong 的高光范围比Blinn的大点
三.使用UnityCG.cgnic中一些常用的函数修改后的代码
Shader "Custom/Gai_fragment sprcular"
{
Properties
{
_Diffuse("Diffuse Color",Color)=(1,1,1,1)
_Specular("Specular Color",Color)=(1,1,1,1)
_Gloss("Gloss",Range(1,50))=20
}
SubShader
{
Pass
{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"Lighting.cginc"
#include"UnityCG.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
half _Gloss;
struct a2v
{
float4 vertex:POSITION; //取得顶点位置
float3 normal:NORMAL;
};
struct v2f
{
float4 svPos:SV_POSITION; //剪裁空间下的顶点坐标
float3 worldNormal:TEXCOORD0;
float4 worldVertex:TEXCOORD1; //世界空间下的顶点坐标
};
v2f vert(a2v v)
{
v2f f;
f.svPos=UnityObjectToClipPos(v.vertex);
f.worldNormal=UnityObjectToWorldNormal(v.normal);
//法线从模型空间=》世界空间
f.worldVertex=mul(unity_ObjectToWorld,v.vertex);
//顶点坐标从模型空间=》世界空间
return f;
}
fixed4 frag(v2f f):SV_TARGET
{
fixed3 normalDir=normalize(f.worldNormal); //法线向量
fixed3 lightDir=normalize(WorldSpaceLightDir(f.worldVertex));
//光线向量
fixed3 viewDir=normalize(UnityWorldSpaceViewDir(f.worldVertex));
//视野方向
fixed3 halfDir=normalize(lightDir + viewDir); //平分向量
fixed3 diffuse=_LightColor0.rgb * _Diffuse.rgb * max(0,dot(lightDir ,normalDir)); //漫反射
fixed3 specular=_LightColor0.rgb * _Specular.rgb * pow ( max(0,dot(normalDir,halfDir) ),_Gloss); //高光反射
fixed3 tempcolor=diffuse+specular+UNITY_LIGHTMODEL_AMBIENT.rgb; //UNITY_LIGHTMODEL_AMBIENT.rgb环境光颜色
return fixed4(tempcolor,1);
}
ENDCG
}
}
FallBack"SPECULAR"
}