OpenGL实现类似Unity Free Aspect Ratio的无拉伸适配方案咨询
问题原因分析
你当前的代码固定正交矩阵的水平范围为0100、垂直范围为0100,正交视锥体的宽高比固定为1:1,和实际屏幕的宽高比不匹配时,视锥体内容映射到屏幕就会产生拉伸。同时编辑器和安卓端的屏幕宽高比不一致时,两端实际可见的坐标范围不同,你在编辑器中放置在边界附近的对象,到安卓端可能会超出视锥体裁剪范围,就会出现显示异常甚至完全不显示的问题。
Unity Free Aspect Ratio 正交相机实现原理
Unity正交相机的Size参数定义的是视口垂直方向的半高,比如Size = 5时,垂直显示范围固定为-5~+5,总高度为10。Free Aspect模式下,正交相机的水平范围会自动根据当前屏幕的宽高比计算:水平半宽 = Size * 屏幕宽高比,最终正交视锥体的宽高比和屏幕宽高比完全一致,所以映射到屏幕后所有对象都能保持原始比例,不会出现拉伸。
通用适配方案
根据你的需求,有两种常用的无拉伸适配方案,不需要强制固定编辑器和安卓端的分辨率:
- 固定垂直范围适配(推荐多数2D游戏使用)
逻辑和Unity正交相机逻辑一致,固定垂直方向的显示范围,水平范围随屏幕宽高比自动扩展,所有设备上垂直方向的内容完全一致,宽屏设备可以看到更多左右两侧的内容,不会有拉伸。
代码示例:GoldState::aspectRatio = m_AspectRatio = (float)width / (float)height; float orthoDown = 0.0f; float orthoUp = 100.0f; // 固定垂直显示范围0~100 float orthoLeft = 0.0f; float orthoRight = 100.0f * m_AspectRatio; // 水平范围随宽高比动态计算 m_OrthoMatrix = glm::ortho(orthoLeft, orthoRight, orthoDown, orthoUp); - 固定设计分辨率+黑边适配
先定一个设计分辨率的基准宽高比(比如常用的9:16),所有设备都按这个比例等比缩放内容,居中显示,超出屏幕的部分留黑边,所有设备上可见的内容范围完全一致,不会出现部分设备对象显示不全的问题,适合需要精确控制关卡显示范围的场景。
代码示例:const float DESIGN_ASPECT = 9.0f / 16.0f; // 自定义设计分辨率宽高比 GoldState::aspectRatio = m_AspectRatio = (float)width / (float)height; float viewportX = 0, viewportY = 0; float viewportW = width, viewportH = height; if (m_AspectRatio > DESIGN_ASPECT) { // 设备屏幕更宽,上下留黑边 viewportH = width / DESIGN_ASPECT; viewportY = (height - viewportH) / 2.0f; } else { // 设备屏幕更高,左右留黑边 viewportW = height * DESIGN_ASPECT; viewportX = (width - viewportW) / 2.0f; } // 先调用glViewport设置显示区域 glViewport(viewportX, viewportY, viewportW, viewportH); // 正交矩阵固定使用设计分辨率对应的范围 m_OrthoMatrix = glm::ortho(0.0f, 100.0f * DESIGN_ASPECT, 0.0f, 100.0f);
补充说明
如果你的游戏不需要适配不同宽高比的设备,也可以直接固定关卡编辑器的分辨率,安卓端使用和编辑器一致的分辨率做等比缩放+黑边适配,这种方案实现逻辑最简单,不会出现两端内容显示不一致的问题。
内容的提问来源于stack exchange,提问作者GoldSpark
相关产品推荐
相关产品推荐

