发生相机变换时场景渲染不稳定

Scene rendering wonky when camera transformations occur

我最近切换到 GLM 来管理我的矩阵和向量,但是当我更改我的变量(例如摄像机角度或位置)时,整个渲染场景变得混乱。

除了伸个懒腰真不知道怎么形容了

问题:

注:

这是我在渲染函数中实现相机的方式(alpha 和 beta 是旋转变量,默认情况下 = 0,camX 和 camY 是平移变量,默认情况下也 = 0):

glm::mat4x4 mMatrix;
glm::mat4x4 vMatrix;

glm::mat4x4 cameraTransformation;
cameraTransformation = glm::rotate(cameraTransformation, glm::radians(alpha)/*alpha*(float)M_PI/180*/, glm::vec3(0, 1 ,0));
cameraTransformation = glm::rotate(cameraTransformation, glm::radians(beta)/*beta*(float)M_PI/180*/, glm::vec3(1, 0, 0));

glm::vec4 cameraPosition = (cameraTransformation * glm::vec4(camX, camY, distance, 0));
glm::vec4 cameraUpDirection = cameraTransformation * glm::vec4(0, 1, 0, 0);

vMatrix = glm::lookAt(glm::vec3(cameraPosition[0],cameraPosition[1],cameraPosition[2]), glm::vec3(camX, camY, 0.0), glm::vec3(cameraUpDirection[0],cameraUpDirection[1],cameraUpDirection[2]));

glm::mat4x4 glmat = pMatrix * vMatrix * mMatrix;
QMatrix4x4 qmat = QMatrix4x4(glmat[0][0],glmat[0][1],glmat[0][2],glmat[0][3],
                             glmat[1][0],glmat[1][1],glmat[1][2],glmat[1][3],
                             glmat[2][0],glmat[2][1],glmat[2][2],glmat[2][3],
                             glmat[3][0],glmat[3][1],glmat[3][2],glmat[3][3]);
shaderProgram.bind();
shaderProgram.setUniformValue("mvpMatrix", qmat);

我这样设置投影矩阵(fov = 30 度):

pMatrix = glm::perspective( glm::radians(fov), (float)width/(float)height, (float)0.001, (float)10000 );

我的矩阵在使用时看起来像这样:

这是它的外观示例

在任何更改之前,所有值均为 0:

当 camX 变为 14 时(注意,我没有旋转我的相机!):

我犯了一个非常愚蠢的错误!

在尝试将我的 glm::mat4x4 转换为 QMatrix4x4 时,我不小心调换了行和列。

我需要更改:

QMatrix4x4 qmat = QMatrix4x4(glmat[0][0],glmat[0][1],glmat[0][2],glmat[0][3],
                             glmat[1][0],glmat[1][1],glmat[1][2],glmat[1][3],
                             glmat[2][0],glmat[2][1],glmat[2][2],glmat[2][3],
                             glmat[3][0],glmat[3][1],glmat[3][2],glmat[3][3]);

至:

QMatrix4x4 qmat = QMatrix4x4(glmat[0][0],glmat[1][0],glmat[2][0],glmat[3][0],
                             glmat[0][1],glmat[1][1],glmat[2][1],glmat[3][1],
                             glmat[0][2],glmat[1][2],glmat[2][2],glmat[3][2],
                             glmat[0][3],glmat[1][3],glmat[2][3],glmat[3][3]);
glm::mat4x4 cameraTransformation;
cameraTransformation = glm::rotate(cameraTransformation, glm::radians(alpha)/*alpha*(float)M_PI/180*/, glm::vec3(0, 1 ,0));
cameraTransformation = glm::rotate(cameraTransformation, glm::radians(beta)/*beta*(float)M_PI/180*/, glm::vec3(1, 0, 0));

这可以通过使用矩阵乘法和使用不同的 glm 调用来简化:

glm::mat4x4 cameraTransformation =
glm::rotate(glm::radians(alpha), glm::vec3(0,1,0)) *
glm::rotate(glm::radians(beta), glm::vec3(1,0,0));

下一个:

glm::vec4 cameraPosition = (cameraTransformation * glm::vec4(camX, camY, distance, 0));
glm::vec4 cameraUpDirection = cameraTransformation * glm::vec4(0, 1, 0, 0);

在矢量的 w 分量中有一个零表示该矢量是一个方向,而不是一个位置。然而,您正在获得一个位置向量作为输出。这恰好有效,因为cameraTransformation只有旋转操作,没有平移操作,但最好清楚:

glm::vec3 cameraPosition = glm::vec3(cameraTransformation * glm::vec4(camX, camY, distance, 1));

注意-我使用的是 vec3 而不是 vec4,因为我就是喜欢这样做。

对于下一部分,您实际上需要方向向量而不是位置向量,因此 w 分量中应该有一个零。仍然将它转换为 vec3,因为在我看来它更清晰。

glm::vec3 cameraUpDirection = glm::vec3(cameraTransformation * glm::vec4(0, 1, 0, 0));

下一个:

vMatrix=
glm::lookAt(glm::vec3(cameraPosition[0],cameraPosition[1],cameraPosition[2]),
glm::vec3(camX, camY, 0.0),
glm::vec3(cameraUpDirection[0],cameraUpDirection[1],cameraUpDirection[2]));

Glm 允许您将 vec3 作为构造函数参数传递给 vec4,因此您可以像这样缩短代码:

vMatrix=
glm::lookAt(glm::vec3(cameraPosition),
glm::vec3(camX, camY, 0.0),
glm::vec3(cameraUpDirection));

但我们甚至不需要这样做,因为我将变量更改为 vec3s 而不是 vec4s:

vMatrix= glm::lookAt(cameraPosition, glm::vec3(camX, camY, 0.0), cameraUpDirection);

最后,您可以使用 .x.y.z.w 而不是 [] 运算符,我认为它更安全,更易于阅读。