1、漫反射:
黑话:
常用向量:(全要记)
nDir:法线方向,点乘操作,简称,n;
lDir:光照方向,点乘操作,简称,l;
vDir:观察方向,点乘操作,简称,v;
rDir:光反射方向,点乘操作,简称,r;
hDir:半角方向(Halfway),lDir和vDir的中间角方向,点乘操作,简称h;
所在空间:
OS:ObjectSpace 物体空间,本地空间。
WS:WorldSpace 世界空间。
VS:ViewSpace 观察空间。
CS:HomogenousClipSpace 齐次裁剪空间??
TS:TangentSpace 切线空间。??
TXS:TextureSpace 纹理空间。??
2、镜面反射phong:
phong:光反射方向和视角方向越重合,反射越强。
Blling实现思路01:
1、光的方向=实际上是=光方向的反方向。这里获取到正值,所以 乘 -1,获取正常光方向。
2、反射沿 法线 反射,=得到= 光的反射方向(rDir)。
3、观察方向(vDir) 点乘 光的反射方向(rDir) == 镜面反射 Blling
4、点乘过后有 负值 ,这里负值截断,(Max=0)>>(小于0的数值,都压到 0).
5、添加Slider,控制Power(叠加),收紧高光 次数,得到最终Blling(反射效果)。
Blling实现思路02:
1、视角反射 * 光方向 == 反射(Blling)。
Blinn-phong:法线方向和半角方向越重合,反射越强。
实现思路:
1、half Dir 半角反射,点乘 法线方向 =得到= 半反射(Bliinn-Phong)。
Bliinn-Phong 与 Phong的区别:
Bliinn-Phong 相比 Phong性能消耗减少一半,无力效果不及Phong。
3、代码>>漫反射&&镜面反射:
代码段 实现OldShool光照模型 (油腻 巧克力反射 效果) 思路:
准备阶段:
1、使用 shaderForge 最简模板 备用。
2、改命名路径,改命名路径,改命名路径。
3、书写 基础 Lambert 漫反射 光照模型。
关于声明几个不同公开类型的格式:
Properties段定义参数的格式:
·格式:_名称("面板标签",类型(参数,可无))=默认值
关于不同类型的公开声明示例:
顶点(身份证)输入声明 要和 屏幕转换一致(匹配身份信息)
前缀修饰字符知识:
修饰字:
uniform:共享于 Vert(顶点) , 和 Frag(像素)。
attibute:仅限于 Vert(顶点)。
Varying:用于 Vert 和 Frag 传数据。
转像素声明类型的知识:
顶点转像素阶段,没有Color之类的类型声明,只有:
1、Float
2、Float2
3、Float3
4、Float4
5、Half
代码实现思路:
像素获取阶段:
原料:
1、posCS:拿到屏幕空间顶点位置 转像素 o.posSC=UnityObjectToClipPos(v.vertex)
2、posWS:拿到世界空间顶点位置 转像素 o.posWS=mul(unity_ObjectToWorld,v.vertex)
3、 nDirWS:世界空间法线方向 转像素 o.nDirWS=UnityObjectToWorldNormal(v.normal)
像素shader阶段:
目标:
1、得到一个 Lambert(漫反) + Bliiing(反射)的效果。
阶段:
1、准备向量
获取法线(nDir):
float3 nDir = i.nDirWS;
获取光向量(lDir):
float3 lDir = _WorldSpaceLightPos0.xyz;
获取观察方向(vDir),并归一化:
观察方向= 摄像机位置 - 世界顶点像素位置(posWS)
normallize(float3 vDir = _WorldSpaceCameraPoss.xyz - i . posWS);
获取半角光向量(hDir):== 视角方向和光方向的中间角。
光方向半角 = 归一化后的 ( 视角方向 + 光方向)。
float3 hDir = normalize( vDir + lDir)
2、准备点积结果
获取 n&l 的点乘结果(法线 & 灯光)
float ndotl = dot(nDir , lDir);
获取 n&h 的点乘结果(法线 & 半角反射)
float ndoth = dot(nDir , hDir);
3、光照模型
赋值截断 基础光照模型
float lambert = max(0.0 , ndotl );
赋值截断,反射光照模型,并叠加_SpecularPow 次。
float blinnphong = pow(max(0.0 , ndoth) , _SpecularPow);
最终结果:
float3 finalRGB = _MainCol * lambert + blinnPhong;
(好习惯:这里建议拿三维的乘一维的东西,因为结果是三维的)。
4、返回结果
return float4(finalRGB ,1.0);
预想阶段:
1、基础兰伯特Lambert着色代码段,
2、color色彩Public 可控制修改。
3、高光,叠加(Powor)次数 可控制修改。
4、作业:
代码段案例。
重点公式精华:
1、Lambert(基础光照)
Lambert=(法线 点积 灯光)
Lambert = dot(nDir , lDir);
2、blinnphong(反射)
blinnphong=(法线 点积 半角反射)
blinnphong = dot(nDir,hDir);
3、Phong (高光反射)
float3 rdir = reflect(-ldir,ndir); //反射 是由 光照方向 反射出法线 的。
Phong = dot(vdir,rdir); // 反射 和 摄像机 反应,就是 高光反射.
Shader "Unlit/Sc05_SL_OldSchool04"
{
Properties
{
_MainCol("MainColor",Color)=(1,1,1,1)
_SpecularPow("SpecularPow",Range(0,90))=30
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass {
Name "FORWARD"
Tags {
"LightMode"="ForwardBase"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "UnityCG.cginc"
#pragma multi_compile_fwdbase_fullshadows
#pragma target 3.0
UNITY_INSTANCING_BUFFER_START( Props )
// UNITY_DEFINE_INSTANCED_PROP( float4, _Color)
UNITY_INSTANCING_BUFFER_END( Props )
//同步通知全局 声明了他们。
uniform float3 _MainCol;
uniform float _SpecularPow;
//输入结构
struct VertexInput
{
float4 vertex : POSITION;
float4 normal : NORMAL;
};
//顶点输出结构 准备工作 法线(法线是依存于光的,所以如下命名), UV ,顶点啊 ,等等 声明变量
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);
//获取输出世界空间位置像素;
o.posWS = mul(unity_ObjectToWorld,v.vertex);
o.nDirWS = UnityObjectToWorldNormal(v.normal);
return o ;
}
//色彩输出结构
float4 frag(VertexOutput i) : COLOR
{
//1、向量准备
float3 nDir = i.nDirWS;
float3 lDir = _WorldSpaceLightPos0.xyz;
//摄像机向量 = 相机位置 - 对象位置(世界空间)
float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS);
//半角反射向量 = 相机位置 + 灯光位置
float3 hDir = normalize(vDir + lDir);
float3 rdir = reflect(-ldir,ndir);// 反射 = (光向量,法线向量)
//2、点积结果准备 lambert=(法线 点积 灯光) blinnphong=(法线 点积 半角反射)
float ndotl = dot(nDir,lDir);//Lambert
float ndoth = dot(nDir,hDir);//blinPhong
float rdotv = dot(rdir,vdir);//Phong
//3、光照模型公式:
float lambert = max(0,ndotl);
float Phong = pow(max(0,rdotv),_SpecularPow);
float blinnPhong = pow(max(0,ndoth),_SpecularPow);
float3 finalRGB = _MainCol * lambert + blinnPhong;
//float3 finalRGB = _MainCol * lambert + Phong;
//4、返回输出
return float4 (finalRGB,1);
}
ENDCG
}
}
}