- 两个向量点乘:A*C=|A||C|cosθ
- Normalize(A):使一个向量单位化。
- 叉乘:A*B=C ,C向量与A、B垂直。
- 矩阵A和它的逆矩阵相乘结果是单位矩阵。
- 正交矩阵:矩阵的逆是矩阵的转置。AAT=E。矩阵的组成向量是单位正交基。正交向量的作用是,在运算过程中求矩阵的逆运算量很大,而求矩阵的转置运算量小,可以把求矩阵的逆转换为求矩阵的转置(比如世界坐标和屏幕坐标的互相转换。)
- 齐次坐标系:把三阶的矩阵扩展为四阶。齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换。
- 常用的坐标变换:
所以点的最后坐标是1,向量的最后一位是0,因为向量的平移是没有意义的。
- 空间转换:
Shader语言中,float 32位; half 16位; fixed 11位
diffuse 颜色的四维变量:RGB和透明度值 每个变量最大值1.0
a2v应用到顶点结构。v2f:顶点到片段
- 漫反射光照模型:
- 根据光源的重要程度分为三种不同的处理方式:
逐像素处理(per-pixel)、逐顶点处理(per-vertex)、SH简化处理
光源的处理方式RenderMode分为Not Important 和Important。
Not Important是逐顶点处理或SH,Important是逐像素处理。最亮的平行光是逐像素。在QualitySetting中可以设置逐像素处理光源数目。逐顶点处理光源最多4个。
在ForwardBase Pass中,处理一个逐像素光源和全部的SH/逐顶点光源。
在ForwardAdd Pass中处理单个逐像素光源。
- 漫反射改进1:将顶点着色改为片段着色,阴暗交界处的颜色会呈现的更平滑
Shader"Lesson/SimpleDiffuse2"
{
Properties{
_Diffuse("DiffuseColor",Color)=(1,1,1,1)
}
Subshader{
Pass{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM//运用CG
#pragma vertex vert
#pragma fragment frag //define name
#include "Lighting.cginc"
fixed4 _Diffuse;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f{
float4 Pos:SV_POSITION;
fixed3 worldNormal:TEXCOORD0;//0-7 储存一部分自定义的数据
};
v2f vert(a2v v){
v2f o;
o.Pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=normalize(mul((float3x3)unity_ObjectToWorld,v.normal));
return o;
}
fixed4 frag(v2f IN):SV_TARGET{ //在片段着色
float3 lDir=normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse =_LightColor0*_Diffuse*saturate(dot(IN.worldNormal,lDir));
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 _color =ambient+diffuse;
return fixed4(_color,1.0);
}
ENDCG
}
}
}
效果对比:左边顶点着色,右边片段着色
漫反射改进2:防止背面出现死黑
Shader"Lesson/ValveDiffuse"
{
Properties{
_Diffuse("DiffuseColor",Color)=(1,1,1,1)
_ValveIndex("ValveIndex",Range(0.0,1.0))=0.5
}
Subshader{
Pass{
Tags{"LightMode"="ForwardBase"}
CGPROGRAM//运用CG
#pragma vertex vert
#pragma fragment frag //define name
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed _ValveIndex;
struct a2v{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f{
float4 Pos:SV_POSITION;
fixed3 worldNormal:TEXCOORD0;//0-7 储存一部分自定义的数据
};
v2f vert(a2v v){
v2f o;
o.Pos=UnityObjectToClipPos(v.vertex);
o.worldNormal=normalize(mul((float3x3)unity_ObjectToWorld,v.normal));
return o;
}
fixed4 frag(v2f IN):SV_TARGET{
float3 lDir=normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse =_LightColor0*_Diffuse*max(0,(dot(IN.worldNormal,lDir)*_ValveIndex+(1-_ValveIndex)));//让所有的值都在0以上。防止在背部没有光线照射的地方出现死黑。
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 _color =ambient+diffuse;
return fixed4(_color,1.0);
}
ENDCG
}
}
}
效果: