使用 GLM 正交投影矩阵将三角形顶点放在错误的位置

Posted

技术标签:

【中文标题】使用 GLM 正交投影矩阵将三角形顶点放在错误的位置【英文标题】:Triangle Vertexes in wrong place with GLM Orthographic Projection Matrix 【发布时间】:2019-03-26 08:44:22 【问题描述】:

最近,我正在尝试使用 OpenGL 在我的窗口内容视图 (OSX NSView) 中渲染一个三角形(如图 1),我使用 GLM 库函数 glm::ortho 进行“正交投影”,在渲染之后,顶点三角形都在错误的位置,它们似乎与窗口内容视图有偏移。

我有两个问题:

    我是否误解了 glm::ortho(基于以下代码)?

    当窗口调整大小(放大,缩小)时,如何保持三角形在窗口中保持相同的位置(即顶部顶点在宽度中间,底部顶点在角落) ?

结果如下:

我的渲染函数:

- (void)render

    float view_width = self.frame.size.width;
    float view_height = self.frame.size.height;

    glViewport(0, 0, view_width, view_height);
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Using Orthographic Projection Matrix, vertex position
    // using view coordinate(pixel coordinate)
    float positions[] = 
        0.0f,                    0.0f,           0.0f, 1.0f,
        view_width,              0.0f,           0.0f, 1.0f,
        view_width/(float)2.0,   view_height,    0.0f, 1.0f,
    ;

    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), positions);

    glm::mat4 p = glm::ortho(0.0f, view_width, 0.0f, view_height);
    glm::mat4 v = glm::lookAt(glm::vec3(0, 0, 1),  glm::vec3(0, 0, 0),  glm::vec3(0, 1, 0));
    glm::mat4 m = glm::mat4(1.0f);

    // upload uniforms to shader
    glUniformMatrix4fv(_projectionUniform, 1, GL_FALSE, &p[0][0]);
    glUniformMatrix4fv(_viewUniform, 1, GL_FALSE, &v[0][0]);
    glUniformMatrix4fv(_modelUniform, 1, GL_FALSE, &m[0][0]);

    glDrawElements(GL_TRIANGLE_STRIP, sizeof(positions) / sizeof(positions[0]),GL_UNSIGNED_SHORT, 0);

    [_openGLContext flushBuffer];

我的顶点着色器:

#version 410

in vec4 position;
uniform highp mat4 projection;
uniform highp mat4 view;
uniform highp mat4 model;

void main (void)

    gl_Position = position * projection * view * model;

【问题讨论】:

必须是gl_Position = projection * view * model * position; 【参考方案1】:

glm 矩阵的初始化方式与 GLSL 矩阵相同。更多信息请参见The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors, page 101。

一个向量必须从右边乘以矩阵。

见GLSL Programming/Vector and Matrix Operations:

注意向量必须从右边乘以矩阵。

如果一个向量从左边乘以一个矩阵,结果对应于从左边乘一个行向量到矩阵。这对应于从右边将一个列向量与转置矩阵相乘。

这意味着你必须在顶点着色器中改变顶点变换:

gl_Position = position * projection * view * model;

gl_Position = projection * view * model * position;

【讨论】:

【参考方案2】:

@Rabbid76 已经回答了我的第一个问题,它有效!非常感谢。 第二个问题,在 OSX 中,当调整窗口大小(包含 OpenGL 视图)时,应该更新 NSOpenGLContext,如下所示:

- (void)setFrameSize:(NSSize)newSize 
    [super setFrameSize:newSize];
    // update the _openGLContext object
    [_openGLContext update];
    // reset viewport
    glViewport(0, 0, newSize.width*2, newSize.height*2);
    // render
    [self render];

【讨论】:

以上是关于使用 GLM 正交投影矩阵将三角形顶点放在错误的位置的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL中的正交投影矩阵问题

GLSL:如何使用投影矩阵计算光线方向?

投影三角形的表面积

glm中矩阵值的顺序不正确?

使用 OpenGL 3.3 进行实例化似乎很慢

OpenGL中的正交投影问题