代码之家  ›  专栏  ›  技术社区  ›  synchronizer

使用openGL、glm math和正交投影,旋转时扭曲的形状

  •  1
  • synchronizer  · 技术社区  · 7 年前

    为了练习,我正在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);
    

    。。。虽然这显然没有考虑到屏幕的宽度和高度。我见过其他人用宽度和高度代替1s,但这似乎破坏了系统或什么也不显示。

    我使用静态方法旋转,该方法修改包含 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的参数乘以width和height,那么如何变换坐标以使v\u position(我的“in”/“variang”插值版本的position属性)在着色器中以-1到1的方式工作?当涉及到实体放置的便利性时,选择特定坐标系的含义是什么?游戏将使用精灵和纹理,所以我考虑使用像素坐标系,但这很快就变得很难在着色器方面进行推理。我宁愿让它工作。

    谢谢你的帮助。

    编辑:是否可以将我的可变/插值v\U位置设置为计算的gl\U位置值,而不是属性位置?

    1 回复  |  直到 7 年前
        1
  •  3
  •   Tagard    7 年前

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

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