【问题标题】:OpenGL - translation stretches and distorts spriteOpenGL - 平移拉伸和扭曲精灵
【发布时间】:2015-06-20 23:56:14
【问题描述】:

我大致遵循opengl-tutorial.org 上的非常方便的教程。我已经能够创建一个网格,为它绘制一个精灵,并完美地旋转和缩放该网格。

但是,我在尝试转换网格时遇到了一些问题。 (下图)

这是精灵的更新功能:

    Transform* transform = static_cast<Transform*>(owner->GetComponent(CID_TRANSFORM));

    glUseProgram(shaderID_);

    glm::mat4 projection = glm::perspective(45.0f , 4.0f / 3.0f, 0.1f, 100.0f);

    glm::mat4 view = glm::lookAt(
        glm::vec3(3, 3, 3),
        glm::vec3(0, 0, 0),
        glm::vec3(0, 1, 0)
        );

    glm::mat4 model = transform->GetModelMatrix();

    glm::mat4 mvp = projection * view * model;

    GLuint matrixID = glGetUniformLocation(shaderID_, "MVP");

    glUniformMatrix4fv(matrixID, 1, GL_FALSE, &mvp[0][0]);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture_);
    glUniform1i(samplerID_, 0);

    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer_);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glEnableVertexAttribArray(1);
    glBindBuffer(GL_ARRAY_BUFFER, uvBuffer_);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

    glDrawArrays(GL_TRIANGLES, 0, 3 * 2);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);

这里是 getModelMatrix 函数:

glm::mat4 Transform::GetModelMatrix()
{
    glm::mat4 trans = glm::mat4(
        1.0f, 0.0f, 0.0f, translation.x,
        0.0f, 1.0f, 0.0f, translation.y,
        0.0f, 0.0f, 1.0f, translation.z,
        0.0f, 0.0f, 0.0f, 1.0f);

    float xCos = glm::cos(rotation.x);
    float xSin = glm::sin(rotation.x);
    float yCos = glm::cos(rotation.y);
    float ySin = glm::sin(rotation.y);
    float zCos = glm::cos(rotation.z);
    float zSin = glm::sin(rotation.z);

    glm::mat4 xRotation = glm::mat4(
        1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, xCos, -xSin, 0.0f,
        0.0f, xSin, xCos, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    glm::mat4 yRotation = glm::mat4(
        yCos, 0.0f, ySin, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f,
        -ySin, 0.0f, yCos, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    glm::mat4 zRotation = glm::mat4(
        zCos, -zSin, 0.0f, 0.0f,
        zSin, zCos, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    glm::mat4 rot = xRotation * yRotation * zRotation;

    glm::mat4 sca = glm::mat4(
        scale.x, 0.0f, 0.0f, 0.0f,
        0.0f, scale.y, 0.0f, 0.0f,
        0.0f, 0.0f, scale.z, 0.0f,
        0.0f, 0.0f, 0.0f, 1.0f);

    return trans * rot * sca;
}

这是从 (3, 3, 3) 看到的原点处的精灵。

这是从 (3, 3, 3) 看到的转换为 (1, 0, 0) 的精灵。

【问题讨论】:

  • 图片在我看来并不失真,只是正常的透视投影,只是入射角较大。矩形的一部分似乎被平截头体近场剪裁了。
  • @sevatitov:相机没有在两张图片之间移动,唯一的区别是网格沿着 x 轴移动了 1 个单位。在我看来,这会使精灵保持相同的方向,只是向右移动。
  • 我认为 GLM 和 OpenGL 一样,使用列主矩阵。您正在按行主要顺序指定翻译矩阵的元素。
  • @RetoKoradi:啊,我真傻!确实是这样。谢谢!将其重新发布为答案,我会将其标记为正确。

标签: c++ opengl transform translation distortion


【解决方案1】:

与 OpenGL 相匹配,GLM 按列主要顺序存储矩阵。构造函数还期望元素以相同的顺序指定。

但是,您的翻译矩阵是按行主要顺序指定的:

glm::mat4 trans = glm::mat4(
    1.0f, 0.0f, 0.0f, translation.x,
    0.0f, 1.0f, 0.0f, translation.y,
    0.0f, 0.0f, 1.0f, translation.z,
    0.0f, 0.0f, 0.0f, 1.0f);

要以正确的列主顺序指定矩阵,需要:

glm::mat4 trans = glm::mat4(
    1.0f, 0.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f, 0.0f,
    0.0f, 0.0f, 1.0f, 0.0f,
    translation.x, translation.y, translation.z, 1.0f);

【讨论】:

  • 第一段的错字:)
  • @Grimmy 确实!谢谢,现在修好了。
  • 其实这里“列专业”和“行专业”是混在一起的。在“column major”表示法中,翻译元素位于第四个column,而在“row major”表示法中,这些元素位于第四个row
  • @PeterO.No,当前版本应该是正确的。翻译元素总是在最后一列(好吧,至少只要你乘以右边的列向量)。如果矩阵按行主要顺序指定,则它们是元素 3、7 和 11。按列主要顺序,它们是元素 12、13 和 14。
  • 那么应避免使用术语“列专业”和“行专业”以防止混淆。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 2011-08-08
  • 1970-01-01
  • 1970-01-01
  • 2019-05-31
  • 1970-01-01
相关资源
最近更新 更多