在了解到Blinn-Phong高光的基本原理后自己写着玩的(小白一个),虽然还不完善,但是感觉初步效果还行,记录一下自己的思路。
思路: 只考虑单一方向光的情况下,高光是通过计算光方向和视角方向的半角向量和法线向量作点积后进行幂运算得到的,所以我的思路是基于真的视角方向和光方向创造一个假的视角方向和光方向,也就是对真的光方向和视角方向作偏移,来得到额外的高光点,再通过一些参数来实现对高光位置、大小和亮度等进行一个大致的调整。
代码:
Shader "MyShader/myShader3"
{
Properties
{
_BaseColor("Base Color",Color) = (1,1,1,1)
_Specular("Specualr",Range(0,1)) = 1
_SpecularPow("SpecularPow",Range(1,90)) = 30
_Specular1("Specualr1",Range(0,1)) = 1
_SpecularPow1("SpecularPow1",Range(1,90)) = 30
_OffsetX("OffsetX",Range(0,1)) = 1
_OffsetY("OffsetY",Range(0,1)) = 1
_EnvColorIntensity("EnvColorIntensity",Range(0,1)) = 1
_topColor("Top Color", Color) = (1,1,1,1)
_sideColor("Side Color",Color) = (1,1,1,1)
_downColor("Down Color",Color) = (1,1,1,1)
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
half4 _BaseColor;
float _Specular;
float _SpecularPow;
float _Specular1;
float _SpecularPow1;
float _EnvColorIntensity;
float _OffsetX;
float _OffsetY;
half4 _topColor;
half4 _downColor;
half4 _sideColor;
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct VertexOutput
{
float4 pos : SV_POSITION;
float4 posWS : TEXCOORD3;
float3 nDirWS : TEXCOORD0;
LIGHTING_COORDS(1,2)
};
VertexOutput vert(VertexInput v)
{
VertexOutput o;
o.pos = UnityObjectToClipPos(v.vertex);
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.posWS = mul(unity_ObjectToWorld,v.vertex);
TRANSFER_VERTEX_TO_FRAGMENT(o)
return o;
}
half4 frag(VertexOutput i):SV_Target{
float3 nDirWS = normalize(i.nDirWS);
float3 lDirWS = normalize(UnityWorldSpaceLightDir(i.posWS));
float3 vDirWS = normalize(UnityWorldSpaceViewDir(i.posWS));
float lembert = max(0,dot(nDirWS,lDirWS));
float3 fakeLDirWS = lDirWS;
float3 fakeVDirWS = vDirWS;
fakeLDirWS.x *= _OffsetX;
fakeLDirWS.z *= _OffsetY;
fakeVDirWS.x *= _OffsetX;
fakeVDirWS.z *= _OffsetY;
float3 hDirWS = normalize(lDirWS + vDirWS);
float3 hDirWS1 = normalize(fakeLDirWS + fakeVDirWS);
half3 diffuse = lembert * _BaseColor;
half3 specular1 = pow(max(0,dot(nDirWS ,hDirWS)),_SpecularPow) * _Specular;
half3 specular2 = pow(max(0,dot(nDirWS ,hDirWS1)),_SpecularPow1) * _Specular1;
float3 shadow = LIGHT_ATTENUATION(i);
half3 light = (diffuse + specular1 + specular2)*shadow;
//half3 light = (diffuse + specular1)*shadow;
float topLight = max(0,nDirWS.y);
float downLight = max(0,-nDirWS.y);
float sideLight = 1 - topLight - downLight;
half3 EnvLightColor = topLight * _topColor + downLight * _downColor + sideLight * _sideColor;
EnvLightColor *= _EnvColorIntensity;
return half4(EnvLightColor+light,1);
}
ENDCG
}
}
}
效果图: