Search code examples
c++openglglm-mathorthographic

Create an OpenGL 2D view camera but using model view projection cameras


I am trying to create a 2D, top down, style camera in OpenGL. I would like to stick to the convention of using model-view-projection matrices, this is so I can switch between a 3D view and a top down view while the application runs. I am actually using the glm::lookAt method to create the view matrix.

However there is something missing in my understanding. I am rendering a triangle on the screen, [very close to this tutorial][1], and that works perfectly fine (so no problems with windowing, display loops, vertex buffers, etc). The triangle is centered at (0, 0), and vertices are on -0.5/0.5 (so already in NDC).

I then added a uniform mat4 mpv; to the vertex shader. If I set the mpv matrix to:

glm::vec3 camera_pos = glm::vec3(0.0f, 0.0f, -1.0f);
glm::vec3 target_pos = glm::vec3(0.0f, 0.0f, 0.0f);
glm::mat4 view = glm::lookAt(camera_pos, target_pos, glm::vec3(0.0f, 1.0f, 0.0f));

I get the same, unmodified triangle as expected as these are (from my understanding) the default values for OpenGL.

Now I thought if I changed the Z value of the camera position it would have the same effect as zooming in and out, however all I get is the clear color, no triangle is rendered.

    // Trying to simulate zoom in and out by changing z value of camera
    glm::vec3 camera_pos = glm::vec3(0.0f, 0.0f, -3.0f);
    glm::vec3 target_pos = glm::vec3(0.0f, 0.0f, 0.0f);
    glm::mat4 view = glm::lookAt(camera_pos, target_pos, glm::vec3(0.0f, 1.0f, 0.0f));

So I printed the view matrix, and noticed that all I was doing was translating the Z value, which makes sense.

I then added an ortho projection matrix, to make sure everything is in NDC, but I still get nothing.

  // *2 cause im on a Mac/high-res screen and the frame buffer scale is 2.
  // Doing projection * view in one step and just updating view uniform until I get it working.
  view = glm::ortho(0.0f, 800.0f * 2, 0.0f, 600.0f * 2, 0.1f, 100.0f) * view;

Where is my misunderstanding taking place. I would like to:

  1. Simulate a top down view where I can zoom in and out on the target.
  2. Create a 2D camera that follows a target (racing car), so the camera_pos XY and target_pos XY will be the same.
  3. Eventually add an option to switch to a 3D following camera, like a standard racing game 3rd person view, hence the MPV vs just using simple translations. [1]: https://learnopengl.com/Getting-started/Hello-Triangle

Solution

  • The vertex coordinates are in the range [-0.5, 0.5], but the orthographic projection projects the cuboid volume with the left, bottom, near point _(0, 0, 0.1) and the right, top, far point (800.0 * 2, 600.0 * 2, 100) of the viewport.
    Therefore, the triangle mesh just covers one fragment in the lower left of the viewport.

    Change the orthographic projection:

    view = glm::ortho(0.0f, 800.0f * 2, 0.0f, 600.0f * 2, 0.1f, 100.0f) * view;

    view = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 100.0f) * view;