2012-07-12 129 views
2

这里的顶点着色器:OpenTK矩阵变换

uniform mat4 projection; 
uniform mat4 view; 
uniform mat4 model; 

void main(void) 
{ 
    gl_Position = projection * view * model * gl_Vertex; 
    gl_TexCoord[0] = gl_MultiTexCoord0; 
} 

我的理解是,使用不同的转换,所述模型空间是最终变成夹的空间,这是直接吸引到由每个单元在每个轴结合的框视口,即(-1,1,0)处的东西位于视口的左上角。当我删除所有矩阵从着色器变换,

gl_Position = gl_Vertex; 

并传递,作为模型,一个简单的四

public Vector3[] verts = new Vector3[] { 
    new Vector3(-1f, -1f, 0), 
    new Vector3(1f, -1f, 0), 
    new Vector3(1f, 1f, 0), 
    new Vector3(-1f, 1f, 0), 
}; 

public Vector2[] coords = new Vector2[] { 
    new Vector2(0, 1f), 
    new Vector2(1f, 1f), 
    new Vector2(1f, 0f), 
    new Vector2(0f, 0f), 
}; 

public uint[] indices = new uint[] { 
    0,1,2, 
    0,2,3, 
}; 

我得到预期的全屏幕图像。当我应用转换时,图像在屏幕中央显示为一个小方形,正如您所期望的那样。就会出现问题,当我尝试在剪辑中的CPU上的坐标来计算所述模型的顶点的位置:

public Vector4 testMult(Vector4 v, Matrix4 m) 
{ 
    return new Vector4(
     m.M11 * v.X + m.M12 * v.Y + m.M13 * v.Z + m.M14 * v.W, 
     m.M21 * v.X + m.M22 * v.Y + m.M23 * v.Z + m.M24 * v.W, 
     m.M31 * v.X + m.M32 * v.Y + m.M33 * v.Z + m.M34 * v.W, 
     m.M41 * v.X + m.M42 * v.Y + m.M43 * v.Z + m.M44 * v.W); 
} 

Matrix4 test = (GlobalDrawer.projectionMatrix * GlobalDrawer.viewMatrix) * modelMatrix; 

Vector4 testv = (new Vector4(1f, 1f, 0, 1)); 
Console.WriteLine("Test Input: " + testv); 
Console.WriteLine("Test Output: " + Vector4.Transform(testv, test)); 
Vector4 testv2 = testMult(testv, test); 
Console.WriteLine("Test Output: " + testv2); 
Console.WriteLine("Test Output division: " + testv2/testv2.W); 

(传入的矩阵是与传递给所述着色器的那些)

的程序然后前进到得到的裁剪空间外输出,和由W除以0导致区划:

Test Input: (1, 1, 0, 1) 
Test Output: (0.9053301, 1.207107, -2.031746, 0) 
Test Output: (0.9053301, 1.207107, -1, 0) 
Test Output division: (Infinity, Infinity, -Infinity, NaN) 

的矩阵创建如下:

projectionMatrix = Matrix4.CreatePerspectiveFieldOfView((float)Math.PI/4, window.Width/(float)window.Height, 1.0f, 64.0f); 
projectionMatrix = 
(1.81066, 0, 0, 0) 
(0, 2.414213, 0, 0) 
(0, 0, -1.031746, -1) 
(0, 0, -2.031746, 0) 

viewMatrix = Matrix4.LookAt(new Vector3(0,0,4), -Vector3.UnitZ, Vector3.UnitY); 
viewMatrix = 
(1, 0, 0, 0) 
(0, 1, 0, 0) 
(0, 0, 1, 0) 
(0, 0, -4, 1) 

modelMatrix = 
(0.5, 0 , 0 , 0) 
(0 , 0.5, 0 , 0) 
(0 , 0 , 1 , 0) 
(0 , 0 , 0 , 1) 

所以,问题是为什么;我究竟做错了什么?

+0

您可以发布您如何创建三个矩阵(投影,视图和模型),因为这些对于确定您正在进行的转换非常重要。 – Laar 2012-07-12 13:17:07

+0

@Laar - 我已经添加了这个问题,谢谢。 – AStupidNoob 2012-07-13 03:39:53

回答

3

编辑(从评论添加真正的答案)

你OpenTK矩阵默认调换。它看起来使用行向量而不是列向量。因此,您需要将乘法操作为(model * view * proj),而不是(proj * view * model)。或者在上传之前将所有的矩阵转置。


实际上,剪辑空间不是从-1到1,而是从-W到W,其中W是剪辑空间矢量的第四个分量。

你可能想到的是归一化设备coodinates,其范围从-1到1在每个轴上。通过将剪辑空间矢量的X,Y和Z坐标除以剪辑空间W分量得到该值。该部门被称为透视部门

这是在将剪辑空间坐标传递给gl_Position之后在幕后完成的。

虽然您的剪辑空间坐标为0,但这对我来说似乎并不正确。

这里有一些更多的细节:OpenGL FAQ : Transformations

+0

谢谢。我尝试了你的建议,显然导致了分歧。任何想法为什么可能会发生?我添加了一个自定义矩阵*矢量函数来暴露我可能做错的任何事情。 – AStupidNoob 2012-07-13 03:41:06

+1

您可以继续并发布您的整个Matrix4和Vector4类吗?有太多未知的功能可以肯定。你也可以很好地格式化并显示你的3个矩阵的原始值(类似于你对模型矩阵的方式)。 @AStupidNoob – Tim 2012-07-13 04:05:21

+0

Matrix4和Vector4类来自OpenTK,所以它们应该没问题。我已经添加了值,谢谢你的帮助。此外,我注意到,当我使用我的函数来乘以矩阵和向量时,它产生与内置的“Vector4.Transform”函数在矩阵转置时相同的结果... – AStupidNoob 2012-07-13 04:11:35