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

时间:2015-02-15 18:56:03

标签: c++ matrix camera transformation glm-math

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

除了拉伸和移动到处之外,我真的不知道如何描述它。

问题:

  • “相机”转换(例如平移相机)会导致奇怪的非典型/意外更改。通常,当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 );

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

这是一个看起来如何的例子

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

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

2 个答案:

答案 0 :(得分:1)

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而不是vec4 s:

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

最后,您可以使用glm.x.y.z而不是.w来访问[]向量的组件我认为操作符更安全,更容易阅读。

答案 1 :(得分:0)

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

在尝试将我的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]);