欢迎加入Unity业内qq交流群:956187480
qq扫描二维码加群
基本光照模型中高光反射部分的计算模型:
计算高光反射我们需要知道四个参数:入射光线的颜色跟强度,材质的高光反射系数,视角方向v以及反射方向r。
其中反射方向r可以由表面法线n和光源方向l计算:,此公式我们可以用函数reflect(i,n),i入射方向跟n法线方向
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
Shader "a幻世界/SpecularVertex"
{
Properties
{
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
_Specular ("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
_Gloss ("Gloss", Range(8, 256)) = 20 //控制高光范围
}
SubShader
{
Pass{
Tags { "RenderType" = "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 color : COLOR;
};
v2f vert(a2v v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);//模型空间顶点转换到裁剪空间
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//获取环境光
fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));//把模型空间的法线转换到世界坐标
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);//获取世界空间的光方向
fixed3 diffuse = _LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal, worldLightDir));//计算漫反射
fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));//计算反射方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz-UnityObjectToClipPos(v.vertex));//相机的世界坐标-顶点转换到世界空间=世界空间下的视角方向
fixed3 specular = _LightColor0.rgb*_Specular.rgb*pow(saturate(dot(reflectDir,viewDir)), _Gloss);//代入公式计算高光
o.color = ambient + diffuse + specular;
return o;
}
fixed4 frag(v2f i):SV_Target {
return fixed4(i.color,1);
}
ENDCG
}
}
FallBack "Specular"
}
二.逐像素高光反射,按照逐像素处理我们就能得到更加平滑的高光效果
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "a幻世界/SpecularPixel"
{
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
_Specular("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
_Gloss("Gloss", Range(8, 256)) = 20 //控制高光范围
}
SubShader
{
Pass{
Tags { "RenderType" = "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 {
fixed3 ambienm = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rbg*_Diffuse.rgb*saturate(dot( worldLightDir, worldNormal ) );
fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb*_Specular.rbg*pow(saturate(dot(reflectDir, viewDir ) ),_Gloss);
return fixed4(ambienm+diffuse+specular,1);
}
ENDCG
}
}
FallBack "Specular"
}
三.Blinn-Phong光照模型,高光反射部分看起来更大更亮一些。而具体在实际渲染中选择哪一种我们要视情况而定
Shader "a幻世界/SpecularBlinnPhong"
{
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
_Specular("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
_Gloss("Gloss", Range(8, 256)) = 20 //控制高光范围
}
SubShader
{
Pass{
Tags { "RenderType" = "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 {
fixed3 ambienm = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rbg*_Diffuse.rgb*saturate(dot(worldLightDir, worldNormal));
fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfDir = normalize(worldLightDir+viewDir);
fixed3 specular = _LightColor0.rgb*_Specular.rbg*pow(max(0,dot(worldNormal, halfDir)),_Gloss);
return fixed4(ambienm + diffuse + specular,1);
}
ENDCG
}
}
FallBack "Specular"
}
四.使用Unity内置函数来写shader以上面的模型为例
Shader "a幻世界/SpecularBlinnPhongUseBuildInunction"
{
Properties
{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1) //漫反射颜色
_Specular("Specular", Color) = (1, 1, 1, 1) //控制高光的反射颜色
_Gloss("Gloss", Range(8, 256)) = 20 //控制高光范围
}
SubShader
{
Pass{
Tags { "RenderType" = "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 = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) :SV_Target {
fixed3 ambienm = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize( UnityWorldSpaceLightDir(i.worldPos));
fixed3 diffuse = _LightColor0.rbg*_Diffuse.rgb*saturate(dot(worldLightDir, worldNormal));
fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
fixed3 halfDir = normalize(worldLightDir + viewDir);
fixed3 specular = _LightColor0.rgb*_Specular.rbg*pow(max(0,dot(worldNormal, halfDir)),_Gloss);
return fixed4(ambienm + diffuse + specular,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
欢迎加入Unity业内qq交流群:956187480
qq扫描二维码加群