(三)UnityCG文件简析
unity封装了很多方法可以直接调用,省去了很多复杂的矩阵计算,其中最基本的文件是UnityCG.cginc。在pass中通过#include "UnityCG.cginc"添加引用,然后就可以引入里面定义的代码块、方法以及变量。相关文件放置在安装目录下相关位置,如Unity\Editor\Data\CGIncludes。
在上一篇中我们自定义了struct变量,如下所示:
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
其实完全可以采用此文件中定义的类型appdata_full,其定义如下,只是没有必要传递如此多的数据,对资源是一种浪费。
struct appdata_full
{
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 texcoord1 : TEXCOORD1;
float4 texcoord2 : TEXCOORD2;
float4 texcoord3 : TEXCOORD3;
fixed4 color : COLOR;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
如果需要将法线从模型坐标系转化到世界坐标系,则可以直接调用如下方法,如果自己手动处理则需要自己计算normalize(mul(norm, (float3x3)unity_WorldToObject));,由于法线向量的特殊问题,直接通过左乘m矩阵则计算错误。
inline float3 UnityObjectToWorldNormal( in float3 norm )
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
return UnityObjectToWorldDir(norm);
#else
// mul(IT_M, norm) => mul(norm, I_M) => {dot(norm, I_M.col0), dot(norm, I_M.col1), dot(norm, I_M.col2)}
return normalize(mul(norm,float3x3)unity_WorldToObject));
#endif
}
在pass中调用TANGENT_SPACE_ROTATION即可调用
float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w;
float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal )
可以直接使用rotation 进行切线空间的相关计算。