Python中的OpenGL透视矩阵

2024-04-25 00:13:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试用python构建一个透视转换矩阵,以便与pyOpenGL一起使用。我的视图和模型转换正在工作,但是当我应用投影变换时,我得到一个空白屏幕(应该是从(0,0,+1)看到原点处的一个三角形)。在

我已经看了一遍数学,据我所知,这个变换应该行得通,所以我需要另一双眼睛来帮助找到问题。在

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需要它的地方。我试着在不换位的情况下发送矩阵,它对输出没有(可见的)影响。在

这里是顶点着色器:

^{pr2}$

有人能确定我的转变可能存在哪些问题吗?在

编辑:我已经得到了输出矩阵,并手工完成了计算。应用透视分割后,截锥边缘上的所有点都将沿着NDC框显示,近点和远点的z分别被转换为-1、+1(由于舍入误差,精度为+/-minor)。对我来说,这说明我的数学是对的,问题在别处。这是输出矩阵:

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

Tags: ofnumpyviewfield矩阵数学mathmatrix
2条回答

我已经解决了问题,发布信息以防将来有人遇到类似的问题。在

在构建模型、视图和投影矩阵时,我引入了行主矩阵和列主矩阵的混合。引入这些是因为numpy和OpenGL需要不同格式的矩阵。当单独操作这些矩阵是有效的,因为它们可以很容易地用numpy进行转置以产生正确的结果。在

合并婚姻时出现了问题。结果是这些转换以一种不一致和毫无意义的顺序进行,所有的点都被从屏幕上划掉了。这就隐藏了透视矩阵中的错误和复杂的调试。在

解决方案是确保所有矩阵在它们存储数据的方式上是一致的(要么全部是行主矩阵,要么是列主矩阵),并且在发送到OpenGL之前进行一次转换。在

既然您说您是从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;

请注意以下行:

^{pr2}$

将其与您的等效项进行比较:

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

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

相关问题 更多 >