twe*_*ypi 3 math directx vector hlsl
从这个网站:http://www.toymaker.info/Games/html/vertex_shaders.html
我们有以下代码段:
// transformations provided by the app, constant Uniform data
float4x4 matWorldViewProj: WORLDVIEWPROJECTION;
// the format of our vertex data
struct VS_OUTPUT
{
float4 Pos : POSITION;
};
// Simple Vertex Shader - carry out transformation
VS_OUTPUT VS(float4 Pos : POSITION)
{
VS_OUTPUT Out = (VS_OUTPUT)0;
Out.Pos = mul(Pos,matWorldViewProj);
return Out;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么结构VS_OUTPUT有一个4维向量作为它的位置?位置只是x,y和z?
因为您需要w坐标进行透视计算.从顶点着色器输出后,DirectX通过除以w来执行透视除法.
基本上如果你有32768,-32768,32768,65536作为你的输出顶点位置,那么在w除以后得到0.5,-0.5,0.5,1.此时w可以被丢弃,因为它不再需要.然后,该信息通过视口矩阵传递,该矩阵将其转换为可用的2D坐标.
编辑:如果您查看如何使用投影矩阵执行矩阵乘法,您可以看到值如何放置在正确的位置.
采用D3DXMatrixPerspectiveLH中指定的投影矩阵
2*zn/w 0 0 0
0 2*zn/h 0 0
0 0 zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0
Run Code Online (Sandbox Code Playgroud)
并将其应用于随机x,y,z,1(注意顶点位置w将始终为1)顶点输入值得到以下
x' = ((2*zn/w) * x) + (0 * y) + (0 * z) + (0 * w)
y' = (0 * x) + ((2*zn/h) * y) + (0 * z) + (0 * w)
z' = (0 * x) + (0 * y) + ((zf/(zf-zn)) * z) + ((zn*zf/(zn-zf)) * w)
w' = (0 * x) + (0 * y) + (1 * z) + (0 * w)
Run Code Online (Sandbox Code Playgroud)
您可以立即看到w和z不同.w coord现在只包含传递给投影矩阵的z坐标.z包含更复杂的东西.
所以..假设我们有一个输入位置(2,1,5,1)我们有一个zn(Z-Near)为1和一个zf(Z-Far为10)和aw(宽度)为1和ah(高度)1.
通过我们得到这些价值
x' = (((2 * 1)/1) * 2
y' = (((2 * 1)/1) * 1
z' = ((10/(10-1) * 5 + ((10 * 1/(1-10)) * 1)
w' = 5
Run Code Online (Sandbox Code Playgroud)
扩展我们然后得到
x' = 4
y' = 2
z' = 4.4
w' = 5
Run Code Online (Sandbox Code Playgroud)
然后,我们进行最终的视角分割
x'' = 0.8
y'' = 0.4
z'' = 0.88
w'' = 1
Run Code Online (Sandbox Code Playgroud)
现在我们有了最终的坐标位置.这假设x和y的范围是-1到1,z的范围是0到1.正如您所看到的,顶点在屏幕上.
作为一个奇怪的奖励你可以看到,如果| x'| 或| y'| 或| z'| 大于| w'| 或者z'小于0表示顶点在屏幕外.此信息用于将三角形剪切到屏幕.
无论如何,我认为这是一个非常全面的答案:D
Edit2:警告我正在使用ROW主要矩阵.列主要矩阵被转置.
旋转由 3 维矩阵指定,平移由向量指定。通过将它们组合成一个 4 x 3 矩阵,您可以在“单个”操作中执行这两种转换:
rx1 rx2 rx3 tx1
ry1 ry2 ry3 ty1
rz1 rz2 rz3 tz1
Run Code Online (Sandbox Code Playgroud)
但是,由于这不是方阵,因此无法执行各种操作(一个反演)。通过添加额外的行(什么都不做):
0 0 0 1
Run Code Online (Sandbox Code Playgroud)
所有这些操作都成为可能(如果不容易的话)。
正如 Goz 在他的回答中解释的那样,通过使“1”成为非单位值,矩阵变成了透视变换。