庄懂-BoyanTata的个人空间_哔哩哔哩_Bilibili
漫反射-Diffuse
镜面反射-Specular

常用向量


漫反射
跟Camera或者人眼的观察视角无关

镜面反射
跟Camera或者人眼的观察视角有关系
phong 光的反射与人眼的视角方向越重合(夹角越小),反射越强,反之,夹角越大,高光越暗

半角向量h 光方向L与视角方向V的中间方向
float3 halfVector = normliaze(viewDirection + lightDirection);
halfAngle = normalize(normalize(lightDirection) + normalize(eyeDirection));
为什么半角向量是两个向量相加?
https://www.zhihu.com/question/25266627

半角h与法线n的夹角越小,镜面高光越强
半角h与法线n的夹角越大,镜面高光越弱

Phong

始终要明确的一点是光的方向L实际是(现实中)光的反方向

取反,乘以-1,就取到光方向了

reflect(L,N) 光方向与法线方向

Blinn-Phong

Phong比Blinn_Phong的效果要好,但计算量也高,Blinn_Phong的计算量低,性能好

节点练习
Phong

Blinn-Phong

Old_School效果



观察方向 = 眼镜的位置 - (世界空间下)点的位置
float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);


Shader "AP01/L05/OldSchool"
{
Properties
{
_MainCol ("颜色", color) = (1.0, 1.0, 1.0, 1.0)
_SpecularPow ("高光次幂", range(1, 90)) = 30
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
Name "FORWARD"
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
// 输入参数
// 修饰字(满足小朋友太多的问好, 想保发量的大家看热闹)
// uniform 共享于vert,frag
// attibute 仅用于vert
// varying 用于vert,frag传数据
uniform float3 _MainCol; // RGB够了 float3
uniform float _SpecularPow; // 标量 float
// 输入结构
struct VertexInput
{
float4 vertex : POSITION; // 顶点信息 Get✔
float4 normal : NORMAL; // 法线信息 Get✔
};
// 输出结构
struct VertexOutput
{
float4 posCS : SV_POSITION; // 裁剪空间(暂理解为屏幕空间吧)顶点位置
float4 posWS : TEXCOORD0; // 世界空间顶点位置
float3 nDirWS : TEXCOORD1; // 世界空间法线方向
};
// 输入结构>>>顶点Shader>>>输出结构
VertexOutput vert (VertexInput v)
{
VertexOutput o = (VertexOutput)0; // 新建输出结构
o.posCS = UnityObjectToClipPos( v.vertex ); // 变换顶点位置 OS>CS
o.posWS = mul(unity_ObjectToWorld, v.vertex); // 变换顶点位置 OS>WS
o.nDirWS = UnityObjectToWorldNormal(v.normal); // 变换法线方向 OS>WS
return o; // 返回输出结构
}
// 输出结构>>>像素
float4 frag(VertexOutput i) : COLOR
{
// 准备向量
float3 nDir = normalize(i.nDirWS);
float3 lDir = _WorldSpaceLightPos0.xyz;
float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS.xyz);
float3 hDir = normalize(vDir + lDir);
// 准备点积结果
float ndotl = dot(nDir, lDir);
float ndoth = dot(nDir, hDir);
// 光照模型
float lambert = max(0.0, ndotl);
float blinnPhong = pow(max(0.0, ndoth), _SpecularPow);
float3 finalRGB = _MainCol * lambert + blinnPhong;
// 返回结果
return float4(finalRGB, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}