本篇主要用于记录自己的实战操作,以及一些碎碎念(观后感),如果有什么好想法或者本篇出现什么错误,请多指教~
本篇的内容参考视频:庄懂的技术美术入门课(美术向)
使用软件:Unity 2019 3.6f1 ,ShaderForge
本篇主要内容包含:漫反射与镜面反射,Phong与Blin Phong连连看,代码编写Phong/blinn-Phong+lambert,创意题
一.漫反射与镜面反射
1.漫反射
- 漫无目的,四面八方均匀的散射;
- 效果类似电影幕布;
- 光学模型:如lambert(nDir点乘lDir,vDir不参与)
- 因为向四面八方均匀散射,所以反射亮度与观察者看的方向无关;
2.镜面反射
- 有目的,沿镜面方向,不均匀的散射;
- 类似效果如镜子
- 光学模型:如Phong(rDir点乘vDir,光反射方向与视角方向越重合,反射越强),Blinn-Phong(nDir点乘hDir,法线方向与半角方向越重合,反射越强)
- 因为反射具有明显的方向性,观察者视角决定反射光的有无和明暗;
3.常见的一些向量命名
4.空间常用命名
二.Phong与Blinn-Phong
1.Phong
如下图max节点前可以选择上面的连接方式也可选择下面的方式,两者等价,Power节点用于求指数函数,这里的效果类似于PS里正片叠底;
2.Blinn-Phong
3.两者对比
上图中左边为Blinn-Phong,右边为Phong;
Phong模型比起Blinn-Phong模型更为仿真,但是Blinn-Phong的开销较少,但如今的设备上两者差别不大,但还是尽可能降低开销,除非必须要更仿真的Phong。
三.代码编写
先认识一些操作
1.Lambert+blinn-Phong
Shader "Custom/co5-LP"
{
Properties{
_MainColor("颜色",color) = (1.0,1.0,1.0,1.0)
_SpecularPow("高光次幂",range(1,90)) = 30
}
SubShader{
Tags {"RenderType" = "Opaque"}
Pass {
Tags {"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform float3 _MainColor;
uniform float _SpecularPow;
struct VertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct VertexOutput {
float4 posCS : SV_POSITION;//裁剪空间顶点位置
float4 posWS : TEXCOORD0; //世界空间顶点位置
float3 nDirWS : TEXCOORD1; //世界空间法线方向
};
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);//变换法线方向OS->WS
o.posWS = mul(unity_ObjectToWorld, v.vertex);//变换顶点位置OS->WS
o.posCS = UnityObjectToClipPos(v.vertex);//变换顶点位置OS->CS
return o;
}
float4 frag(VertexOutput i) : COLOR {
//向量
float3 nDir = normalize(i.nDirWS);
float3 lDir = normalize(_WorldSpaceLightPos0.xyz);
float3 vDir = normalize( _WorldSpaceCameraPos.xyz-i.posWS);
float3 hDir = normalize(lDir + vDir);
//中间数据
float ndotl = dot(nDir, lDir);
float ndoth = dot(nDir, hDir);
//光照模型
float Lambert = max(0, ndotl);
float blinnPhong = pow(max(0, ndoth),_SpecularPow);
float3 finalcolor = _MainColor * Lambert + blinnPhong;
//返回结果
return float4(finalcolor,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
2.Lambert+Phong
连连看的样式如下,然后,我们根据连连看的逻辑来编写代码;
Shader "Unlit/co5-LoPcode"
{
Properties{
_MainColor("颜色",color) = (1.0,1.0,1.0,1.0)
_SpecularPow("高光次幂",range(1,30)) = 15
}
SubShader{
Pass {
Tags {
"LightMode" = "ForwardBase"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform float3 _MainColor;
uniform float _SpecularPow;
struct VertexInput {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct VertexOutput {
float4 posCS : SV_POSITION;
float4 posWS :TEXCOORD0;
float3 nDirWS : TEXCOORD1;
};
VertexOutput vert(VertexInput v) {
VertexOutput o = (VertexOutput)0;
o.nDirWS = UnityObjectToWorldNormal(v.normal);
o.posWS = mul(unity_ObjectToWorld, v.vertex);
o.posCS = UnityObjectToClipPos(v.vertex);
return o;
}
float4 frag(VertexOutput i) : COLOR {
//向量
float3 nDir = normalize(i.nDirWS);
float3 lDir = normalize(_WorldSpaceLightPos0.xyz);
float3 vDir = normalize(_WorldSpaceCameraPos.xyz - i.posWS);
float3 rDir = reflect(-1 * lDir, nDir);
//中间数据
float rdotv = dot(rDir, vDir);
float ndotl = dot(nDir, lDir);
//光照模型
float Lambert = max(0, ndotl);
float Phong = pow(max(0, rdotv), _SpecularPow);
float3 finalColor = _MainColor * Lambert + Phong;
//
return float4(finalColor,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
四.创意思考
先回顾下学过的东西,Lambert与Phong两个光照模型,调子映射,屏幕UV纹理,RGB三色截断,Lut,lerp(遮罩);
创意思路:利用Phong+Lambert构筑光照模型,明暗分别处理,明部使用纹理映射,暗部另搞一套纹理;
节点如下图
最后效果如下图: