OpenGL:从原点翻译时模型拉伸
OpenGL: Model stretched when translated from origin
我正在开发一个 space 飞行模拟器作为我的第一个真正的 OpenGL 项目。当立方体不在原点时,我无法正确渲染立方体。发生的情况是立方体从原点向外伸展,伸展的程度取决于从原点平移的量。
我认为这与着色器无关,因为我尝试了两种不同的顶点着色器,结果相同。其中一个着色器是一个非常简单的着色器:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
// Output data ; will be interpolated for each fragment.
out vec3 fragmentColor;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
// The color of each vertex will be interpolated
// to produce the color of each fragment
fragmentColor = vec3(255,255,255);
}
我很清楚问题不在于着色器。
当立方体在每个方向平移 1 个单位时,它看起来像这样:
在正 Z 方向平移相机时,立方体会拉伸更多以跟随相机。
翻译前(相机位于(0,0,25),模型位于(5,5,5))
MVP 矩阵:
(10.942525, 0.000000, 12.402489, 12.500000)
(0.000000, 14.590034, 12.402489, 12.500000)
(0.000000, 0.000000, 12.302468, 12.400000)
(0.000000, 0.000000, 24.804977, 25.000000)
转换矩阵:
(0.100000, 0.000000, 0.000000, 0.500000)
(0.000000, 0.100000, 0.000000, 0.500000)
(0.000000, 0.000000, 0.100000, 0.500000)
(0.000000, 0.000000, 0.000000, 1.000000)
平移后(相机在正z方向平移)
转换矩阵:
(0.100000, 0.000000, 0.000000, 0.500000)
(0.000000, 0.100000, 0.000000, 0.500000)
(0.000000, 0.000000, 0.100000, 0.500000)
(0.000000, 0.000000, 0.000000, 1.000000)
MVP 矩阵:
(10.942525, 0.000000, 46.159237, 46.250000)
(0.000000, 14.590034, 46.159237, 46.250000)
(0.000000, 0.000000, 46.059216, 46.150002)
(0.000000, 0.000000, 92.318474, 92.500000)
这是我从模型中获取变换矩阵的代码:
glm::mat4 MovableObject::getTransformationMatrix() const
{
return getTranslationMatrix() * getRotationMatrix() * getScaleMatrix();
}
glm::mat4 MovableObject::getScaleMatrix() const
{
glm::mat4 scaleMatrix = glm::mat4(1.0);
scaleMatrix[0][0] = scaleFactors[0];
scaleMatrix[1][1] = scaleFactors[1];
scaleMatrix[2][2] = scaleFactors[2];
return scaleMatrix;
}
glm::mat4 MovableObject::getRotationMatrix() const
{
return glm::toMat4(rotation);
}
glm::mat4 MovableObject::getTranslationMatrix() const
{
glm::mat4 translationMatrix = glm::mat4(1.);
translationMatrix[0][3] = center[0];
translationMatrix[1][3] = center[1];
translationMatrix[2][3] = center[2];
return translationMatrix;
}
下面是绘制网格的渲染代码:
void Mesh::render(glm::mat4 modelMatrix, const Camera& camera)
{
glUseProgram(programID);
glm::mat4 view = camera.getViewMatrix();
glm::mat4 pvm = camera.getProjectionMatrix() * view * modelMatrix;
std::cout << "MVP Matrix: " << glm::to_string(pvm) << std::endl << std::endl;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &pvm[0][0]);
glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, &modelMatrix[0][0]);
glUniformMatrix4fv(viewMatrixID, 1, GL_FALSE, &view[0][0]);
glUniform3f(lightID, 0.f, 0.f, 0.f); // TODO: hardwiring at 0 for now
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// Set "myTextureSampler" sampler to user Texture Unit 0
glUniform1i(textureID, 0);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
这是获取相机矩阵的代码:
glm::mat4 Camera::getProjectionMatrix() const
{
return glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 1000.0f);
}
glm::mat4 Camera::getViewMatrix() const
{
glm::mat4 matrix = glm::toMat4(rotation);
glm::vec3 up = glm::vec3(matrix[0][1], matrix[1][1], matrix[2][1]);
glm::vec3 forward = -glm::vec3(matrix[0][2], matrix[1][2], matrix[2][2]);
return glm::lookAt(center, center + forward, up);
}
glm 使用列优先存储顺序,因此您必须以 m[col][row] 的形式访问元素。您的 getTranslationMatrix()
函数不遵循该约定,因为翻译向量应该在最后一列中。您打印矩阵数字的代码似乎也解释了转置的内容。
请注意,glm 已经具有通过 GLM_GTX_transform
module 创建旋转、缩放和平移等变换矩阵的功能。
我不得不假设直接访问矩阵成员的函数存在问题
glm::mat4 MovableObject::getScaleMatrix() const {
glm::mat4 scaleMatrix = glm::mat4(1.0);
scaleMatrix[0][0] = scaleFactors[0];
scaleMatrix[1][1] = scaleFactors[1];
scaleMatrix[2][2] = scaleFactors[2];
return scaleMatrix;
}
glm::mat4 MovableObject::getTranslationMatrix() const
{
glm::mat4 translationMatrix = glm::mat4(1.);
translationMatrix[0][3] = center[0];
translationMatrix[1][3] = center[1];
translationMatrix[2][3] = center[2];
return translationMatrix;
}
你为什么要这样做而不是更安全
glm::mat4 MovableObject::getScaleMatrix() const {
return glm::scale(glm::mat4(), scaleFactors);
}
glm::mat4 MovableObject::getTranslationMatrix() const {
return glm::translate(glm::mat4(), center);
}
我正在开发一个 space 飞行模拟器作为我的第一个真正的 OpenGL 项目。当立方体不在原点时,我无法正确渲染立方体。发生的情况是立方体从原点向外伸展,伸展的程度取决于从原点平移的量。
我认为这与着色器无关,因为我尝试了两种不同的顶点着色器,结果相同。其中一个着色器是一个非常简单的着色器:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
// Output data ; will be interpolated for each fragment.
out vec3 fragmentColor;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1);
// The color of each vertex will be interpolated
// to produce the color of each fragment
fragmentColor = vec3(255,255,255);
}
我很清楚问题不在于着色器。
当立方体在每个方向平移 1 个单位时,它看起来像这样:
在正 Z 方向平移相机时,立方体会拉伸更多以跟随相机。
翻译前(相机位于(0,0,25),模型位于(5,5,5))
MVP 矩阵:
(10.942525, 0.000000, 12.402489, 12.500000)
(0.000000, 14.590034, 12.402489, 12.500000)
(0.000000, 0.000000, 12.302468, 12.400000)
(0.000000, 0.000000, 24.804977, 25.000000)
转换矩阵:
(0.100000, 0.000000, 0.000000, 0.500000)
(0.000000, 0.100000, 0.000000, 0.500000)
(0.000000, 0.000000, 0.100000, 0.500000)
(0.000000, 0.000000, 0.000000, 1.000000)
平移后(相机在正z方向平移)
转换矩阵:
(0.100000, 0.000000, 0.000000, 0.500000)
(0.000000, 0.100000, 0.000000, 0.500000)
(0.000000, 0.000000, 0.100000, 0.500000)
(0.000000, 0.000000, 0.000000, 1.000000)
MVP 矩阵:
(10.942525, 0.000000, 46.159237, 46.250000)
(0.000000, 14.590034, 46.159237, 46.250000)
(0.000000, 0.000000, 46.059216, 46.150002)
(0.000000, 0.000000, 92.318474, 92.500000)
这是我从模型中获取变换矩阵的代码:
glm::mat4 MovableObject::getTransformationMatrix() const
{
return getTranslationMatrix() * getRotationMatrix() * getScaleMatrix();
}
glm::mat4 MovableObject::getScaleMatrix() const
{
glm::mat4 scaleMatrix = glm::mat4(1.0);
scaleMatrix[0][0] = scaleFactors[0];
scaleMatrix[1][1] = scaleFactors[1];
scaleMatrix[2][2] = scaleFactors[2];
return scaleMatrix;
}
glm::mat4 MovableObject::getRotationMatrix() const
{
return glm::toMat4(rotation);
}
glm::mat4 MovableObject::getTranslationMatrix() const
{
glm::mat4 translationMatrix = glm::mat4(1.);
translationMatrix[0][3] = center[0];
translationMatrix[1][3] = center[1];
translationMatrix[2][3] = center[2];
return translationMatrix;
}
下面是绘制网格的渲染代码:
void Mesh::render(glm::mat4 modelMatrix, const Camera& camera)
{
glUseProgram(programID);
glm::mat4 view = camera.getViewMatrix();
glm::mat4 pvm = camera.getProjectionMatrix() * view * modelMatrix;
std::cout << "MVP Matrix: " << glm::to_string(pvm) << std::endl << std::endl;
// Send our transformation to the currently bound shader,
// in the "MVP" uniform
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &pvm[0][0]);
glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, &modelMatrix[0][0]);
glUniformMatrix4fv(viewMatrixID, 1, GL_FALSE, &view[0][0]);
glUniform3f(lightID, 0.f, 0.f, 0.f); // TODO: hardwiring at 0 for now
// Bind our texture in Texture Unit 0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
// Set "myTextureSampler" sampler to user Texture Unit 0
glUniform1i(textureID, 0);
// 1st attribute buffer : vertices
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(
0, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 2nd attribute buffer : UVs
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, uvBuffer);
glVertexAttribPointer(
1, // attribute
2, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Draw the triangles !
glDrawArrays(GL_TRIANGLES, 0, vertices.size() );
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
}
这是获取相机矩阵的代码:
glm::mat4 Camera::getProjectionMatrix() const
{
return glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 1000.0f);
}
glm::mat4 Camera::getViewMatrix() const
{
glm::mat4 matrix = glm::toMat4(rotation);
glm::vec3 up = glm::vec3(matrix[0][1], matrix[1][1], matrix[2][1]);
glm::vec3 forward = -glm::vec3(matrix[0][2], matrix[1][2], matrix[2][2]);
return glm::lookAt(center, center + forward, up);
}
glm 使用列优先存储顺序,因此您必须以 m[col][row] 的形式访问元素。您的 getTranslationMatrix()
函数不遵循该约定,因为翻译向量应该在最后一列中。您打印矩阵数字的代码似乎也解释了转置的内容。
请注意,glm 已经具有通过 GLM_GTX_transform
module 创建旋转、缩放和平移等变换矩阵的功能。
我不得不假设直接访问矩阵成员的函数存在问题
glm::mat4 MovableObject::getScaleMatrix() const {
glm::mat4 scaleMatrix = glm::mat4(1.0);
scaleMatrix[0][0] = scaleFactors[0];
scaleMatrix[1][1] = scaleFactors[1];
scaleMatrix[2][2] = scaleFactors[2];
return scaleMatrix;
}
glm::mat4 MovableObject::getTranslationMatrix() const
{
glm::mat4 translationMatrix = glm::mat4(1.);
translationMatrix[0][3] = center[0];
translationMatrix[1][3] = center[1];
translationMatrix[2][3] = center[2];
return translationMatrix;
}
你为什么要这样做而不是更安全
glm::mat4 MovableObject::getScaleMatrix() const {
return glm::scale(glm::mat4(), scaleFactors);
}
glm::mat4 MovableObject::getTranslationMatrix() const {
return glm::translate(glm::mat4(), center);
}