1
votes

Rencently, I am trying to render a triangle(as Figure 1) in my Window Content View (OSX NSView) using OpenGL, I make an "Orthographic projection" with GLM library function glm::ortho, after render, the vertexes of the triangle are all in wrong place, they seems has an offset to the Window Content View.

I have 2 questions:

  1. Am I misunderstood about glm::ortho(base the following code)?

  2. When the window resize(Zoom In, Zoom Out), How to keep the triangle retain the same place in the Window(i.e. the top vertex at the middle of the width, and the bottom vertexes at the corner)?

The following is the result:

enter image description here

my render function:

- (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];
}

my vertex shader:

#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;
}
2
It has to be gl_Position = projection * view * model * position;Rabbid76

2 Answers

1
votes

A glm matrix is initialized in the same way as GLSL matrix. See The OpenGL Shading Language 4.6, 5.4.2 Vector and Matrix Constructors, page 101 for further information.

A vector has to be multiplied to the matrix from the right.

See GLSL Programming/Vector and Matrix Operations:

Note that the vector has to be multiplied to the matrix from the right.

If a vector is multiplied to a matrix from the left, the result corresponds to multiplying a row vector from the left to the matrix. This corresponds to multiplying a column vector to the transposed matrix from the right.

This means you've to change the vertex transformation in the vertex shader:

gl_Position = position * projection * view * model;

gl_Position = projection * view * model * position;
0
votes

@Rabbid76 has answered my first question, it works! Thanks a lot. The second question, in OSX, when resizing a window(contain a OpenGL View), the NSOpenGLContext should be update, like this:

- (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];
}