发生相机变换时场景渲染不稳定
Scene rendering wonky when camera transformations occur
我最近切换到 GLM 来管理我的矩阵和向量,但是当我更改我的变量(例如摄像机角度或位置)时,整个渲染场景变得混乱。
除了伸个懒腰真不知道怎么形容了
问题:
- "Camera" 平移相机等变换会导致奇怪的 atypical/unexpected 变化。通常,当像 X 和 Y 这样的相机平移变量偏离“0”时
注:
- 我过去常常对 Qt 的 QMatrix4x4 和 QVector3D 数据类型执行这些非常相同类型的转换,而不是 glm::mat4x4 和 glm::vec4, 并且它有效很好
这是我在渲染函数中实现相机的方式(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));
但我们甚至不需要这样做,因为我将变量更改为 vec3
s 而不是 vec4
s:
vMatrix= glm::lookAt(cameraPosition, glm::vec3(camX, camY, 0.0), cameraUpDirection);
最后,您可以使用 .x
、.y
、.z
、.w
而不是 []
运算符,我认为它更安全,更易于阅读。
我最近切换到 GLM 来管理我的矩阵和向量,但是当我更改我的变量(例如摄像机角度或位置)时,整个渲染场景变得混乱。
除了伸个懒腰真不知道怎么形容了
问题:
- "Camera" 平移相机等变换会导致奇怪的 atypical/unexpected 变化。通常,当像 X 和 Y 这样的相机平移变量偏离“0”时
注:
- 我过去常常对 Qt 的 QMatrix4x4 和 QVector3D 数据类型执行这些非常相同类型的转换,而不是 glm::mat4x4 和 glm::vec4, 并且它有效很好
这是我在渲染函数中实现相机的方式(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));
但我们甚至不需要这样做,因为我将变量更改为 vec3
s 而不是 vec4
s:
vMatrix= glm::lookAt(cameraPosition, glm::vec3(camX, camY, 0.0), cameraUpDirection);
最后,您可以使用 .x
、.y
、.z
、.w
而不是 []
运算符,我认为它更安全,更易于阅读。