一、理论介绍
1、点乘(或点积 Dot):结果为标量
2、意义:一个向量在另一个向量的投影长度
3、表现:两向量相同,结果为1(白色)
两向量相反,结果为-1(黑色)
两向量垂直,结果为0(黑色)
二、计算方法
1、设:模型表面垂直方向为向量nDir(即法线方向)
光照方向的反方向为向量LDir
2、由于负数没有实际意义,因此常用范围max(0,nDir,LDir),称之为兰伯特光照模型
3、兰伯特光照模型:如下图所示
由于不受光照的地方值为0,导致暗的地方会呈现死黑的样子,因此→(往下看)
4、半兰伯特光照模型:
1)计算方法:对明度*0.5后再+0.5
2)特点:比Lambert更透气,不至于暗部至黑
5.映射
1)Append节点介绍:将两个标量转化为一个向量(UV)
三、脚本编写
Shader "Shader/U3D_001" {
Properties {
}
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
//输入结构
struct VertexInput {
float4 vertex : POSITION; //将模型的顶点信息输入进来
float3 normal : NORMAL; //将模型的法线信息输入进来
};
//输出结构
struct VertexOutput {
float4 pos : SV_POSITION; //由顶点信息换算而来的顶点屏幕位置
float3 nDirws:TEXCOORDO; //由模型法线信息换算来的世界空间法线信息
};
//输入结构>>>顶点Shader>>>输出结构
VertexOutput vert (VertexInput v) {
VertexOutput o = (VertexOutput)0; //新建一个输出结构
o.pos = UnityObjectToClipPos( v.vertex ); //交换顶点信息,并将其塞给输出结构
o.nDirws=UnityObjectToWorldNormal(v.normal); //变换法线信息,并将其塞给输出结构
return o; //将输出结构 输出
}
//输出结构>>像素Shader
float4 frag(VertexOutput i) : COLOR {
float3 nDir=i.nDirws; //获取nDir
float3 lDir=normalize(_WorldSpaceLightPos0.xyz); //获取IDir
float nDotl=dot(nDir,lDir); //nDir点乘IDir
//float lambert=max(0.0,nDotl); //截断负值
float lambert=nDotl*0.5f+0.5f;
return float4(lambert,lambert,lambert,1.0); //输出其最终颜色
}
ENDCG
}
}
FallBack "Diffuse"
CustomEditor "ShaderForgeMaterialInspector"
}