从此网站: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?
答案 0 :(得分:9)
因为您需要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
并将其应用于随机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 coord现在只包含传递给投影矩阵的z坐标。 z包含更复杂的东西。
所以..假设我们的输入位置为(2,1,5,1),我们的zn(Z-Near)为1,zf(Z-Far为10),aw(宽度)为1和啊(身高)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主要矩阵。列主要矩阵被转置。
答案 1 :(得分:4)
旋转由3维矩阵指定并由矢量平移。您可以通过将它们组合成单个4 x 3矩阵来执行“单个”操作中的两个变换:
rx1 rx2 rx3 tx1
ry1 ry2 ry3 ty1
rz1 rz2 rz3 tz1
然而,由于这不是正方形,因此存在无法执行的各种操作(一个反转)。通过添加额外的行(无效):
0 0 0 1
所有这些操作都成为可能(如果不容易的话)。
正如Goz在his answer中解释的那样,通过使“1”成为非同一性值,矩阵成为透视变换。
答案 2 :(得分:1)
剪切是此过程的重要部分,因为它有助于可视化几何体的变化。剪切阶段实质上丢弃了原始中位于以原点为中心的2单元立方体之外的任何点(好的,你必须重建部分剪切但在这里无关紧要的图元)。
有可能构建一个直接将世界空间坐标映射到这样一个立方体的矩阵,但从远处平面到近平面的逐渐移动将是线性的。也就是说,当距离观察者一英里时,一只脚(朝向观察者)的移动将导致与距离相机几英尺处的一只脚的移动相同的尺寸增加。
但是,如果我们在向量(w)中有另一个坐标,我们可以将向量分组为w,并且我们的基元不会表现出上述行为,但我们仍然可以使它们最终在2中-unit cube above。
有关详细说明,请参阅http://www.opengl.org/resources/faq/technical/depthbuffer.htm#0060和http://en.wikipedia.org/wiki/Transformation_matrix#Perspective_projection。
一个简单的答案就是说,如果你不告诉管道什么是w,那么你没有给它足够的关于你的预测的信息。这可以直接验证,而无需了解管道对它的作用......
您可能知道4x4矩阵可以根据每个部分的功能分成几部分。进行旋转或缩放操作时,左上角的3x3矩阵会发生变化。翻译时会更改第四列。如果您检查透视矩阵,它会改变矩阵的底行。然后,如果您查看Matrix-Vector乘法的完成方式,您会看到矩阵的底行仅影响向量的合成w分量。因此,如果你没有告诉管道w它将没有你所有的信息。