【问题标题】:shapes skewed when rotated, using openGL, glm math, orthographic projection旋转时倾斜的形状,使用 openGL、glm 数学、正交投影
【发布时间】:2018-05-02 23:28:16
【问题描述】:

为了练习,我在 openGL 中设置了一个 2d/正交渲染管道以用于一个简单的游戏,但我遇到了与坐标系相关的问题。

简而言之,旋转会扭曲二维形状,我似乎无法弄清楚为什么。我也不完全确定我的坐标系是否正确。

首先我寻找以前的答案,但以下(最相关的2D opengl rotation causes sprite distortion)表明问题是转换的顺序不正确,但现在我只使用视图矩阵和投影矩阵,乘以正确顶点着色器中的顺序:

gl_Position = projection * view * model vec4(1.0); //(The model is just the identity matrix.)

总结一下我目前的设置: - 我正在成功上传一个应该横跨整个屏幕的四边形:

GLfloat vertices[] = {
   -wf,  hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // top left
   -wf, -hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // bottom left
    wf, -hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // bottom right
    wf,  hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // top right
};
GLuint indices[] = {
    0, 1, 2,  // first Triangle
    2, 3, 0,   // second Triangle
};

wf 和 hf 为 1,我正在尝试使用 -1 到 1 坐标系,因此我不需要按着色器中的分辨率进行缩放(尽管我不确定这样做是否正确。)

我的视口和正交矩阵:

glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
...
glm::mat4 mat_ident(1.0f);
glm::mat4 mat_projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);

...虽然这显然不考虑屏幕宽度和高度。我见过其他人使用宽度和高度而不是 1,但这似乎破坏了系统或什么都不显示。

我使用一个静态方法旋转,该方法修改包含glm::quaternion(时间/1000)的结构以获得秒数:

    main_cam.rotate((GLfloat)curr_time / TIME_UNIT_TO_SECONDS, 0.0f, 0.0f, 1.0f);
// which does: glm::angleAxis(angle, glm::vec3(x, y, z) * orientation)

最后,我将矩阵作为统一传递:

glUniformMatrix4fv(MAT_LOC, 1, GL_FALSE, glm::value_ptr(mat_projection * FreeCamera_calc_view_matrix(&main_cam) * mat_ident));

...并在顶点着色器中相乘

   gl_Position = u_matrix * vec4(a_position, 1.0);
   v_position = a_position.xyz;

全屏四边形在其中心旋转(0, 0,如我所愿),但它的长度和宽度扭曲,这意味着我没有正确设置。

我最好的猜测是我没有创建正确的正交矩阵,但我承认我在堆栈溢出或其他可能有助于调试的地方找不到任何其他东西。大多数答案表明矩阵乘法顺序是错误的,但这里不是这种情况。

第二个问题是——我不应该在 2d 游戏的上下文中将我的坐标设置为 1/-1 吗?我这样做是为了让编写着色器更容易。添加模型矩阵后,我还担心角色/对象的移动。

什么可能导致问题?如果我需要将 gl::ortho 的参数乘以宽度和高度,那么我如何转换坐标,以便 v_position(我的位置属性的“in”/“variing”插值版本)在 -1 到 1 中工作,因为它应该在着色器中?在放置实体方面,选择特定坐标系的含义是什么?游戏将使用精灵和纹理,所以我正在考虑像素坐标系,但这很快就变得非常难以在着色器方面进行推理。我宁愿让这个工作。

感谢您的帮助。

编辑:是否可以将我的可变/插值 v_position 设置为计算的 gl_Position 值而不是属性位置?

【问题讨论】:

    标签: opengl matrix opengl-3 glm-math orthographic


    【解决方案1】:

    尝试在 glm::ortho 的前两个参数中考虑您正在显示的窗口的纵横比,以反映您的显示器的纵横比。

    GLfloat aspectRatio = SCREEN_WIDTH / SCREEN_HEIGHT;
    glm::mat4 mat_projection = glm::ortho(-aspectRatio, aspectRatio, -1.0f, 1.0f, -1.0f, 1.0f);
    

    【讨论】:

    • 我可以在我回到我的系统时尝试这个,但我不是也需要调整顶点坐标吗?或者更确切地说,您的建议不会使在世界上放置物体变得更加困难吗?我想我的问题是:人们通常如何创建一个与分辨率无关的 2d 坐标系,该坐标系在着色器中表现良好,同时还允许在世界中直观地放置对象?问题是我的方法可能有很多问题——在 CPU 和/或着色器中。嗯
    • 无论如何我都不是矩阵领域的专家。但我相信你只需要考虑投影矩阵中的纵横比。我不相信你需要修改你的纹理坐标。我遇到了本教程,它可能会有所帮助,并且在提供的源代码中处理了纵横比的考虑:learnopengl.com/Getting-started/Coordinate-Systems
    • 嗯,我正在使用那个教程,它可以快速跳过正交投影。无论如何,我会在今天晚些时候尝试您的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 2011-08-31
    • 2014-06-09
    相关资源
    最近更新 更多