Unity Shader中各种空间及变换方法

前几天尝试写一个传送门的shader,发现自己对坐标之间的变换掌握的不够熟练,趁着这阵子想整理shader相关的知识点,先把各种空间及之间转换整理一下。

1 模型空间-世界空间-观察空间-裁剪空间

建模时在模型空间进行,模型自带的坐标均为模型空间下的表示。
当模型被放到世界坐标系中时,表达某个模型的位置使用的是世界空间下的坐标,所以模型上对应的某一个点,必须相应的转化为世界空间下的坐标。
从模型空间到世界空间的变换 叫做 模型变换
Unity的Shader中,模型空间的坐标由Renderer直接提供,作为顶点着色器的输入,语义为POSITION。如:

struct appdata
{
    float4 vertex : POSITION;
}

由于我们能看到的渲染图像均是通过摄像机得到的,为了方便后续裁剪、投影等操作,所以在将模型从模型空间变换到世界空间之后,还需要将其转换到观察空间。所谓的观察空间,就是以摄像机位置为原点,摄像机局部坐标轴为坐标轴的坐标系。
从世界空间到观察空间的变换叫做观察变换(视图变换)。

坐标转换到观察空间后,由于直接使用摄像机的平截头体进行裁剪比较复杂(平截头体的边界方程求交困难),所以需要将其转化到裁剪空间。裁剪空间变换的思路是,对平截头体进行缩放,使近裁剪面和远裁剪面变成正方形,使坐标的w分量表示裁剪范围,此时,只需要简单的比较x,y,z和w分量的大小即可。
从观察空间到裁剪空间的变换叫做投影变换
注意,虽然叫做投影变换,但是投影变换并没有进行真正的投影。

在顶点着色器中,模型、观察、裁剪空间的相关变换矩阵一般为以下几个:

别名 定义 含义
UNITY_MATRIX_M unity_ObjectToWorld 模型变换矩阵
UNITY_MATRIX_V unity_MatrixV 视图变换矩阵
UNITY_MATRIX_P glstate_matrix_projection 投影变换矩阵
UNITY_MATRIX_VP unity_MatrixVP 视图投影变换矩阵
UNITY_MATRIX_MV mul(unity_MatrixV, unity_Obj
Unity Shader,求取法线矩阵的逆矩阵通常是为了进行光照计算,尤其是在使用了表面着色器(Surface Shader)时。法线矩阵是由模型变换矩阵的上3x3部分构成的,用于保持法线向量在空间变换后的方向正确。如果模型变换包含了非均匀缩放,则直接使用模型矩阵的逆转置作为法线矩阵会导致光照计算错误。 法线矩阵(Normal Matrix)是模型变换矩阵用于变换法线的矩阵,通常是模型矩阵的逆转置(Inverse Transpose)。在Shader,可以通过内置函数`UNITY_MATRIX_IT_MV`来直接获取模型视图空间下的法线矩阵,或者使用`UNITY_MATRIX_I_MV`获取模型视图空间下的逆转置矩阵,再进行逆矩阵计算。 Unity Shader语言并没有直接的函数可以获取法线矩阵的逆矩阵,但是可以使用`transpose`函数来得到逆转置矩阵,然后使用`inverse`函数来得到逆矩阵。不过,这通常不必要,因为大多数情况下我们只需要逆转置矩阵来正确变换法线向量。如果确实需要法线矩阵的逆矩阵(而非逆转置矩阵),则需要首先使用`transpose`函数得到逆转置矩阵,然后使用`inverse`函数来计算最终的逆矩阵。 以下是一个简单的例子,展示如何在Unity Shader获取并使用法线矩阵(逆转置)来变换法线向量: ```csharp Shader "Custom/NormalMatrixExample" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; float3 normal : TEXCOORD1; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.normal = UnityObjectToWorldNormal(v.normal); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { // 使用法线矩阵(逆转置)变换法线向量 float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, i.normal); // 进行光照计算... return fixed4(normal, 1.0); } ENDCG } } FallBack "Diffuse" } ``` 请注意,上面的代码仅用于演示如何获取和使用法线矩阵,并未包含完整的光照模型计算。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值