# How to make OpenGL rendering resolution independent from its window context resolution?

Can the rendering resolution of OpenGL and the window size (at least for the Windows OS) be separated? For example, I may only want to render at 400x300 resolution, but I want my window size to be 800x600. If so, how is this done?

Yes, but keep in mind the default frame buffer will always be the same size of the window. What you can do is to render your scenes internally into an off-screen (400x300) frame buffer, and then up-scale it to (800x600), you can do this by rendering this into a texture and applying it on a full screen quad, the advantage you will get is your shaders will run less often than with higher resolution. But you will lose quality due to scaling up which will need interpolating the original data in order to fill the bigger image.

One approach to this requirement is to adjust the projection matrix according to the different dimensions. To me you are describing a device dimension (i.e. 800x600) and virtual dimension (400x300)

Note: I use the word dimension instead of resolution and I am assuming an orthographic projection.

If this is the case, and you want to code for the virtual dimension, then you can do this by applying an aspect ratio correction to the projection matrix, without modifying the viewport matrix as I have seen in other examples.

For example:

// Calc ratio correction based on the two dimensions
float correction;
float deviceRatio = deviceWidth / deviceHeight;
float virtualRatio = virtualWidth / virtualHeight;
float xCorrection = deviceWidth / virtualWidth;
float yCorrection = deviceHeight / virtualHeight;

if (virtualRatio < deviceRatio) {
correction = yCorrection;
} else {
correction = xCorrection;
}

// Now when you calc your ortho projection--in this case centered--
// just divide by the correction
float left = -width / 2.0f / correction;
float right = width / 2.0f / correction;
float bottom = -height / 2.0f / correction;
float top = height / 2.0f / correction;

// Now set matrix which includes correction.
glm::mat4 projMatrix = glm::ortho(left, right, bottom, top, 0.1, 100.0f);

// Your viewport remains unchanged and is simply lower-left aligned
// For example
glViewport(0, 0, deviceWidth, deviceHeight);

// For your view matrix I simply "pull it back" a bit.
viewMatrix = glm::translate(viewMatrix, glm::vec3(0, 0, -1.0);

// And then finally you would multiply all your matrices together
// when rendering.
// For example
glm::mat4 mvp = projMatrx * viewMatrix * triangleModelMatrix;