高光反射计算公式(phong模型)C=(C*M)max(0,vr)
m为材质的官泽度,也成反射度,控制高光区域亮点有多大
M是材质的高光反射颜色,控制材质对于高光反射的轻度和颜色
C为光源的颜色和强度
v是观察方向的单位向量
r是反射方向 r=2(法线单位向量n*光源方向向量)法线单位向量-光源方向向量
高光反射计算公式(Blinn模型)C=(C*M)max(0,nh)
n为法线向量的单位向量
h是对观察方向和光源方向取平均后归一化得到的:h(注:单位向量)=(v(注:单位向量)+光源方向)/|(v(注:单位向量)+光源方向)|
下面分别是逐顶点和逐像素两种写法
phong模型 逐顶点:
Shader "study/Chapter6/halfLambertShader" {
Properties{
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_Specular("Specular",Color)=(1,1,1,1)//控制材质高光反射颜色
_Gloss("Gloss",Range(8.0,256)) = 20 //用于控制高光区域的大小
}
SubShader{
Pass{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM #pragma vertex vert
#pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss; struct a2v{
float4 vertex:POSITION;
fixed4 normal:NORMAL;
};
struct v2f{
float4 pos:SV_POSITION;
fixed3 color:COLOR;
};
v2f vert(a2v v){ v2f o;
o.pos=UnityObjectToClipPos(v.vertex); fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
//内置函数写法,下面给出内置函数
//fixed3 worldNormal=normalize(UnityObjectToWorldNormal(v.normal););
fixed3 worldNormal=normalize(mul(v.normal,(float3x3)unity_WorldToObject)); fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLightDir)); //反射方向get the reflect direction in world space
fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal)); //get the view direction in world space
//世界空间下观察方向
fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-mul(unity_ObjectToWorld,v.vertex).xyz); //Computer specular term
fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir,viewDir)),_Gloss); o.color=diffuse+ambient+specular; return o; }
fixed4 frag(v2f i):SV_Target{
return fixed4(i.color,1.0);
} ENDCG
}
}
FallBack "Specular"
}
phong模型 逐像素:
Shader "study/Chapter6/SpecularPixelLevelShader"
{
Properties{
_Diffuse("Diffuse",Color)=(1,1,1,1)
_Specular("Specular",Color)=(1,1,1,1)
_Gloss("Gloss",Range(8.0,256))=20
} SubShader{
Pass{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss; struct a2v{
fixed4 vertex:POSITION;
fixed3 normal:NORMAL;
};
struct v2f{
fixed4 pos:SV_POSITION;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
}; v2f vert(a2v v){
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//使用内置函数写法
//o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
return o;
} fixed4 frag(v2f i): SV_Target{
//环境光、自发光部分
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
//世界空间下法线单位矢量
fixed3 worldNormal=normalize(i.worldNormal);
//世界空间下光源方向单位矢量
fixed3 worldLightDir=normalize(_WorldSpaceCameraPos.xyz);
//漫反射部分
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));
//世界空间下反射光矢量
fixed3 reflectDir=normalize(reflect(-worldLightDir,worldNormal));
//视野方向
fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
//高光
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir,viewDir)),_Gloss);
//最终观察到的光照
return fixed4(ambient+diffuse+specular,1.0);
}
ENDCG
}
}
FallBack "Specular"
}
Blinn模型逐像素
Shader "study/Chapter6/BlinnPhongShader"
{
Properties{
_Diffuse("Diffuse",Color)=(1,1,1,1)
_Specular("Specular",Color)=(1,1,1,1)
_Gloss("Gloss",Range(8.0,256))=20
}
SubShader{
Pass{
Tags{"LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss; struct a2v{ float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f{ float4 pos:SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
}; v2f vert(a2v v){
v2f o;
o.pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
return o;
} fixed4 frag(v2f i):SV_Target{ float3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
//内置函数写法
//float3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0,dot(worldNormal, worldLightDir));
//内置函数写法
//fixed3 viewDir=normalize(UnityWorldSpaceViewDir(i.worldNormal));
fixed3 viewDir=normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
fixed3 halfDir=normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);
return fixed4(ambient+diffuse+specular,1.0);
}
ENDCG
}
}
FallBack "Specular"
}
unity的内置函数
仅用于前向渲染的只有在渲染模式为前向渲染时(“LightMode”=“ForwordBase”或者"LightMode"="ForwordAdd")
这三个函数里的内置变量——WorldSpaceLightPos0等才能被正确赋值。
注:这一篇以及之前漫反射都是单一平行光源下计算的,查看效果时,去掉天空盒,设置方法为window->Lighting->skybox