c++graphicsglm-mathperspectivecamerafieldofview

Why fovy should be unchanged when resizing window


In GLUT we can register a callback when the viewport size is changed. And often the reshape function looks like this, which changes the perspective projection matrix.

void reshape(int width, int height)
{
    w = width;
    h = height;

    glViewport(0, 0, w, h);

    float aspect = (float) w / (float) h;
    float zNear = 0.1;
    float zFar = 99.0;
    float fovy = glm::radians(45.0f);
    projection = glm::perspective(fovy,aspect,zNear,zFar); // Why is fovy unchanged?

    // Now send the updated projection matrix to the shader
    glUniformMatrix4fv(projectionPos, 1, GL_FALSE, &projection[0][0]);
}

Another example is this answer. I don't understand why the fovy (Field-of-View in the Y direction) is a constant that we can choose in all these implementations. Why doesn't it depend on the size of the viewport, such as:

float fovy = 2*glm::atan(h/(2*zNear)); // arc tangent

The viewport is equivalent to the near plane. If the viewport's height is increased or decreased, shouldn't fov also change accordingly? Because the definition of field-of-view is the angle from the bottom of the screen (viewport) to the top of the screen (viewport). I probably missed something very obvious.


Solution

  • When dealing with cameras, we typically prefer to think about real cameras, rather than trigonometry. We want to be able to specify a wide angle lens, or a telephoto, or a standard lens, etc. The ratio of h/(2*zNear) doesn't really give us the ability to control that fov!

    See the implementation of a perspective projection matrix: https://www.khronos.org/opengl/wiki/GluPerspective_code

        ymax = znear * tanf(fovyInDegrees * M_PI / 360.0);
    
    The viewport is equivalent to the near plane. If the viewport's height is increased or decreased, shouldn't fov also change accordingly?
    

    hopefully not. If I take a photo with a 40mm lens on a 35mm film back, the fov of the lens shouldn't change just because I've enlarged the photo to an A3 sized print!