如何在OpenGL与GLFW中实现保持视口分辨率并自适应缩放内容
OpenGL + GLFW 实现 SDL_RenderSetLogicalSize 等价效果
该效果的本质是维持固定的逻辑渲染分辨率,在窗口比例不匹配时通过黑边填充,同时自动缩放内容适配窗口,不需要修改你原有的渲染逻辑,只需要调整视口参数即可实现,具体步骤如下:
1. 定义固定逻辑分辨率
首先设定你要维持的目标逻辑分辨率,所有渲染坐标、投影矩阵都基于这个值设置即可,后续不需要随窗口大小修改:
#define LOGICAL_WIDTH 1280 #define LOGICAL_HEIGHT 720
2. 注册GLFW帧缓冲大小回调
注意要监听帧缓冲大小而非窗口大小,避免高分屏缩放适配问题:
// 全局变量存储计算后的视口参数 int viewportX, viewportY; int viewportW, viewportH; void framebuffer_size_callback(GLFWwindow* window, int width, int height) { float logicalAspect = (float)LOGICAL_WIDTH / LOGICAL_HEIGHT; float windowAspect = (float)width / height; // 计算适配后的视口大小和偏移 if (windowAspect > logicalAspect) { // 窗口更宽,左右加黑边 viewportH = height; viewportW = (int)(height * logicalAspect); viewportX = (width - viewportW) / 2; viewportY = 0; } else { // 窗口更高,上下加黑边 viewportW = width; viewportH = (int)(width / logicalAspect); viewportY = (height - viewportH) / 2; viewportX = 0; } }
在初始化GLFW窗口后注册回调,同时初始化时主动调用一次计算初始视口:
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); int w, h; glfwGetFramebufferSize(window, &w, &h); framebuffer_size_callback(window, w, h);
3. 调整渲染流程
每帧渲染时按以下顺序执行即可:
// 1. 先清屏为黑色(黑边的颜色可自定义修改) glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 2. 设置计算好的视口 glViewport(viewportX, viewportY, viewportW, viewportH); // 3. 正常执行你的渲染逻辑,投影矩阵还是按逻辑分辨率设置即可 // 比如2D正交投影:glOrtho(0, LOGICAL_WIDTH, 0, LOGICAL_HEIGHT, -1, 1);
可选:鼠标坐标适配
如果你需要处理鼠标输入,可以用以下方法将GLFW返回的窗口鼠标坐标转换为逻辑分辨率下的坐标:
void get_logical_mouse_pos(GLFWwindow* window, double* logicalX, double* logicalY) { double winX, winY; glfwGetCursorPos(window, &winX, &winY); // 先转换为帧缓冲坐标(适配高分屏缩放) int winW, winH, fbW, fbH; glfwGetWindowSize(window, &winW, &winH); glfwGetFramebufferSize(window, &fbW, &fbH); float scaleX = (float)fbW / winW; float scaleY = (float)fbH / winH; double fbX = winX * scaleX; double fbY = winY * scaleY; // 减去视口偏移,再按比例转换为逻辑坐标 *logicalX = (fbX - viewportX) * LOGICAL_WIDTH / viewportW; *logicalY = (fbY - viewportY) * LOGICAL_HEIGHT / viewportH; }
原理解释
和SDL的实现逻辑完全一致:
- 清屏的黑色区域就是最终显示的黑边
- 视口外的内容不会被渲染,刚好实现比例锁定
- 渲染逻辑完全基于固定逻辑分辨率,不需要感知窗口大小变化
内容的提问来源于stack exchange,提问作者Shadoww
相关产品推荐
相关产品推荐

