math - 顶点着色器世界变换,我们为什么要用4维向量?

标签 math vector directx 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;
}

我的问题是:为什么结构 VS_OUTPUT 有一个 4 维向量作为它的位置?位置不只是x,y和z吗?

最佳答案

因为您需要 w 坐标进行透视计算。在您从顶点着色器输出之后,DirectX 通过除以 w 来执行透视除法。

本质上,如果您将 32768、-32768、32768、65536 作为输出顶点位置,那么在 w 除之后,您将得到 0.5、-0.5、0.5、1。此时可以丢弃 w,因为不再需要它。然后,此信息通过视口(viewport)矩阵传递,视口(viewport)矩阵将其转换为可用的 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

并将其应用于随机 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)

立即您可以看到 w 和 z 是不同的。 w 坐标现在只包含传递给投影矩阵的 z 坐标。 z 包含更复杂的东西。

所以..假设我们有一个输入位置 (2, 1, 5, 1) 我们有一个 zn (Z-Near) 为 1 和一个 zf (Z-Far 为 10) 和一个 w (宽度) 为 1 和一个 h (高度)为 1。

传递这些值我们得到
x' = (((2 * 1)/1) * 2
y' = (((2 * 1)/1) * 1
z' = ((10/(10-1)  * 5 + ((10 * 1/(1-10)) * 1)
w' = 5

扩展我们然后得到
x' = 4
y' = 2
z' = 4.4
w' = 5

然后我们执行最终的透视划分,我们得到
x'' = 0.8
y'' = 0.4
z'' = 0.88
w'' = 1

现在我们有了最终的坐标位置。这假设 x 和 y 的范围从 -1 到 1,z 的范围从 0 到 1。如您所见,顶点在屏幕上。

作为一个奇怪的奖励,你可以看到如果 |x'|或 |y'|或 |z'|大于 |w'|或 z' 小于 0 表示顶点不在屏幕上。此信息用于将三角形剪裁到屏幕上。

无论如何,我认为这是一个非常全面的答案:D

Edit2:请注意,我正在使用 ROW 主要矩阵。列主要矩阵被转置。

关于math - 顶点着色器世界变换,我们为什么要用4维向量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1605703/

相关文章:

java余弦相似度问题

directx - Direct3D11 : "gradient instruction used in a loop with varying iteration, forcing loop to unroll", 警告:X3570

c++ - C/C++ 数学运算顺序

C# 方法来缩放值?

c++ - 删除 vector 中的元素

c++ - C++高效完成多重转换

c++ - 如果 `vec.erase(find(...) )` 应该以相反的顺序开始搜索,则删除带有 `find` 的元素

c++ - DirectX 11.2 错误 : X3501: 'main' entry point not found

c++ - 地形 segmentation 和深度缓冲区

javascript - 在线可视化数学方程编辑器可以在网站上实现吗?