在使用OpenGL开发的时候遇到了这样一个问题,当程序通过Mac电脑显示的时候,只显示了左下角的1/4画面,但是移动到扩展屏的时候却恢复正常。这是因为屏幕DPI的问题,实际测试下来Mac屏幕的DPI是普通屏幕的2倍,这意味着创建一个800 * 600的窗口在Mac电脑中实际的DPI是 1600 * 1200。

那么如何获取到实际的DPI呢?

GLFWwindow *window;
int width, height;
window = glfwCreateWindow(800, 600, "GuaiK Window", nullptr, nullptr);
glfwGetFramebufferSize(window, &width, &height);

以上代码会把屏幕实际的DPI写入到width和height中。


那么如何让画面显示正常呢?

使用glViewport告诉OpenGL实际的DPI,可以理解成设置一个画布的大小以供绘画吧。所以需要使用实际的DPI。

glViewport(0, 0, width, height);

通常会把glfwGetFramebufferSize和glViewport放在渲染循环中,这样可以确保在窗口切换的时候可以实时调节画布大小,就像这样:

while(!glfwWindowShouldClose(window){
    ......
    // 设置画布大小
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);
    // 开始渲染
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    ........
    glfwSwapBuffers(window);
}

投影计算

glm::ortho(0.0f, static_cast<GLfloat>(800), 
        0.0f, static_cast<GLfloat>(600), -1.0f, 1.0f);

这里将左下角设置为原点(0, 0),并且设置窗口大小为(800, 600),这里直接使用了glfwCreateWindow创建窗口时的大小,我们在开发的时候也以这个为标准,可绘制的区域是从(0, 0)到(800, 600)的范围,那么在高DPI的环境下会怎么办呢?因为我们已经动态获取了屏幕DPI并设置了Viewport,所以OpenGL会自动将(800, 600)通过投影映射到实际DPI的大小而不需要我们做多余的处理。