Search code examples
c++openglzoomingglfwglm-math

How to make 2D Zoom in OpenGL(GLFW, glad)?


I'm trying to implement a simple paint program and now I have a problem with zoom, I can't understand how to do it? I tried to adapt the code from here to myself, but it did not work, I just get a black screen. What my problem?

Not using glut or glew!

Here my camera code:

.h

class Camera2d
{
public:
    Camera2d(const glm::vec3& pos = glm::vec3(0.f, 0.f, 0.f),
         const glm::vec3& up  = glm::vec3(0.f, 1.f, 0.f));
   //~Camera2d();
    void        setZoom(const float& zoom);
    float       getZoom()       const noexcept;
    glm::mat4   getViewMatrix() const noexcept;
    void        mouseScrollCallback(const float& yOffset);
protected:
    void        update();
private:
    // Camera zoom
    float       m_zoom;
    // Euler Angles
    float       m_yaw;
    float       m_pitch;
public:
    // Camera Attributes
    glm::vec3   position;
    glm::vec3   worldUp;
    glm::vec3   front;
    glm::vec3   up;
    glm::vec3   right;
};

.cpp

Camera2d::Camera2d(
    const glm::vec3& pos /* = glm::vec3(0.f, 0.f, 0.f) */,
    const glm::vec3& up  /* = glm::vec3(0.f, 1.f, 0.f) */
    )
    : m_zoom(45.f)
    , m_yaw(-90.f)
    , m_pitch(0.f)
    , position(pos)
    , worldUp(up)
    , front(glm::vec3(0.f, 0.f, -1.f))
{
    this->update();
}
void Camera2d::setZoom(const float& zoom)
{
    this->m_zoom = zoom;
}
float Camera2d::getZoom() const noexcept
{
    return this->m_zoom;
}
glm::mat4 Camera2d::getViewMatrix() const noexcept
{
    return glm::lookAt(this->position, this->position + this->front, this->up);
}

void Camera2d::mouseScrollCallback(const float& yOffset)
{
    if (m_zoom >= 1.f && m_zoom <= 45.f)
        m_zoom -= yOffset;
    else if (m_zoom <= 1.f)
        m_zoom = 1.f;
    else if (m_zoom >= 45.f)
        m_zoom = 45.f;
}

void Camera2d::update()
{
    // Calculate the new Front vector
    glm::vec3 _front;
    _front.x = cos(glm::radians(this->m_yaw)) * cos(glm::radians(this->m_pitch));
    _front.y = sin(glm::radians(this->m_pitch));
    _front.z = cos(glm::radians(this->m_pitch)) * sin(glm::radians(this->m_yaw));
    this->front = glm::normalize(_front);
    // Also re-calculate the Right and Up vector
    this->right = glm::normalize(glm::cross(this->front, this->worldUp));      // Normalize the vectors, because their length gets closer to 0 the more     you look up or down which results in slower movement.
    this->up = glm::normalize(glm::cross(this->right, this->front));
}

and in main i try smth like this in render loop

    // pass projection matrix to shader
    glm::mat4 projection = glm::perspective(glm::radians(camera.getZoom()),
            static_cast<float>(WIDTH) / static_cast<float>(HEIGHT),
            0.1f,
            10000.f);
    shaderProg.setMat4("projecton", projection);
    // camera view transformation
    glm::mat4 view = camera.getViewMatrix();
    shaderProg.setMat4("view", view);

    here i have just 1 model its my white bg-texture
    glm::mat4 model = glm::translate(model, glm::vec3(0.f, 0.f, 0.f));
    model = glm::rotate(model, glm::radians(0.f), glm::vec3(1.0f, 0.3f, 0.5f));
    shaderProg.setMat4("model", model);

All code on github: here


Solution

  • You're working in 2D, forget about the camera, forget about projection, forget about following OpenGL tutorials, they're aimed at 3D graphics.

    What you need is just a rectangle to fill your screen. Start with the vertices at the the corners of the screen, starting from the top-left corner and moving counterclockwise: (-1,1,0) (-1,-1,0) (1,-1,0) (1,1,0). Forget about Z, you're working in 2D.

    You draw on a texture, and the texture coordinates are (0,1) (0,0) (1,0) (1,1), same order as above. Zooming is now just a matter of scaling the rectangle. You have a matrix to determine the scale and one to determine the position. Forget about rotations, front vectors and all that stuff. In the vertex shader you scale and then translate the vertices as usual, in this order. Done.

    To interact for example you can have mouse wheel up increasing the scale factor and mouse wheel down decreasing it. Hold click and move the mouse to change the (x,y) position. Again forget about Z. Throw those values into the vertex shader and do the usual transformations.