2016-02-12 79 views
3

我想在python中使用pyOpenGL创建透视转换矩阵。我的视图和模型转换正在工作,但是当我应用我的投影转换时,我得到一个空白屏幕(应该从(0,0,+ 1)处查看原点处的三角形)。Python中的OpenGL透视矩阵

我已经查看了数学,并且据我所知,转换应该可行,所以我需要第二双眼睛来帮助找到问题。

def perspective(field_of_view_y, aspect, z_near, z_far): 

    fov_radians = math.radians(field_of_view_y) 
    f = math.tan(fov_radians/2) 

    a_11 = 1/(f*aspect) 
    a_22 = 1/f 
    a_33 = (z_near + z_far)/(z_near - z_far) 
    a_34 = -2*z_near*z_far/(z_near - z_far) 

    # a_33 = -(z_far + z_near)/(z_far - z_near) 
    # a_34 = 2*z_far*z_near/(z_far - z_near) 

    perspective_matrix = numpy.matrix([ 
     [a_11, 0, 0, 0],  
     [0, a_22, 0, 0],  
     [0, 0, a_33, a_34],  
     [0, 0, -1, 0]   
    ]).T 

    return perspective_matrix 

projection_matrix = perspective(45, 600/480, 0.1, 100) 
mvp_matrix = projection_matrix * view_matrix * model_matrix 

我转置的矩阵,因为我相当肯定numpy存储矩阵转置为如何OpenGL需要它。我已经尝试发送矩阵而不进行转置,并且它对输出没有(可见的)影响。

这里是顶点着色器:

#version 330 core 

layout(location = 0) in vec3 position; 
uniform mat4 MVP; 

void main() 
{ 
    vec4 p = vec4(position, 1.0); 
    gl_Position = MVP * p; 
} 

能有人认同我的转变可能存在的问题可能是什么?

编辑:我已经采取了输出矩阵,并通过手工计算。在应用透视图之后,沿着NDC框出现截锥体边缘上的所有点,其中近点和远点处的z分别被转换为-1,+1(由于舍入误差而导致+/-微小精度)。对我来说,这表明我的数学是正确的,问题在其他地方。这是输出矩阵:

[ 1.93137085 0.   0.   0.  ] 
[ 0.   2.41421356 0.   0.  ] 
[ 0.   0.   -1.002002 -1.  ] 
[ 0.   0.   0.2002002 0.  ] 
+0

'600/480'总是要返回'1'。使它成为'600.0/480.0'。这应该不是空白屏幕的原因。 –

+0

600/480 = 1.25当我在Python中运行它。 – Francis

+0

http://ideone.com/I9sfXf –

回答

3

既然你说你正在从glm :: perspective开始工作,那么让我们来分析一下你的代码。有一个关键的不契合:

glm::perspective

assert(aspect != valType(0)); 
    assert(zFar != zNear); 

#ifdef GLM_FORCE_RADIANS 
    valType const rad = fovy; 
#else 
    valType const rad = glm::radians(fovy); 
#endif 

    valType tanHalfFovy = tan(rad/valType(2)); 
    detail::tmat4x4<valType> Result(valType(0)); 
    Result[0][0] = valType(1)/(aspect * tanHalfFovy); 
    Result[1][1] = valType(1)/(tanHalfFovy); 
    Result[2][2] = - (zFar + zNear)/(zFar - zNear); 
    Result[2][3] = - valType(1); 
    Result[3][2] = - (valType(2) * zFar * zNear)/(zFar - zNear); 
    return Result; 

注意以下行:

Result[2][2] = - (zFar + zNear)/(zFar - zNear); 

比较它的等效:

a_33 = (z_near + z_far)/(z_near - z_far) 

注意,有一个负号(-)在整个陈述前面。你的版本没有这个。

+0

我已经注意到两个矩阵之间的差异,并检查了这一点,但这不是问题。在改变符号以匹配我的剪辑后,空间坐标也从(-1,+ 1)移动到(+ 3,+ 1)。我认为问题在于别处。 – Francis

+0

好吧,这是问题,由于某种原因,当我早点检查时,没有可见的影响。我猜别的东西是错的,我在改变代码的同时改变了它(我仍然不知道它是什么或者它是如何修复它的)。手指交叉我不会再打破它(这是时间就像这些我感谢我有git)。 – Francis

0

我已经找到了问题,发布信息以防将来遇到类似问题。

在构建模型,视图和投影矩阵时,我引入了行主要矩阵和列主要矩阵的混合。这是因为numpy和OpenGL需要不同格式的矩阵。单独操作时,这些矩阵起作用,因为它们可以用numpy轻松移位以产生正确的结果。

组合基数时出现问题。效果是转换以不一致和毫无意义的顺序进行,所有的点都被屏蔽了。这隐藏了透视矩阵中的错误和复杂的调试。

的解决方案是确保所有矩阵是在它们存储数据(全部行主要或全部列主要)和换位发生一次之前发送到OpenGL的方式一致。