为啥retina屏幕坐标值是像素值的两倍

Posted

技术标签:

【中文标题】为啥retina屏幕坐标值是像素值的两倍【英文标题】:Why retina screen coordinate value is twice the value of pixel value为什么retina屏幕坐标值是像素值的两倍 【发布时间】:2016-04-17 05:15:27 【问题描述】:

我的电脑是配备 13 英寸视网膜屏幕的 Mac pro。屏幕分辨率为1280*800(默认)。

使用以下代码:

gWindow = glfwCreateWindow(800, 600, "OpenGL Tutorial", NULL, NULL);

//case 1
glViewport(0,0,1600,1200);
//case 2
glViewport(0,0,800,600);

案例 1 生成适合窗口的三角形。

案例 2 生成的三角形是窗口大小的 1/4。

一半的视口:

GLFW 文档指出以下内容(来自here):

虽然窗口的大小是用屏幕坐标来衡量的,但 OpenGL 适用于像素。您传递给 glViewport 的大小,例如, 应该以像素为单位。在某些机器上,屏幕坐标和像素 是相同的,但在其他人上它们不会。还有第二套 检索帧缓冲区大小(以像素为单位)的函数 窗口。

为什么我的视网膜屏幕坐标值是像素值的两倍?

【问题讨论】:

贴出绘制三角形的代码。 【参考方案1】:

正如Sabuncu 所说,如果不知道如何绘制三角形,很难知道什么结果应该是正确的。

但我猜您的问题与使用视网膜屏幕这一事实有关,当您使用 2.0 比例因子时,您需要渲染两倍于普通屏幕的像素 - see here

您所使用的方法显示在您的 GLFL 链接下方几行

还有 glfwGetFramebufferSize 用于直接检索窗口的帧缓冲区的当前大小。

int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);

帧缓冲区的大小可能会独立于窗口的大小而改变,例如,如果窗口在常规监视器和高 DPI 监视器之间拖动。

在您的情况下,我打赌您将获得的帧缓冲区大小将是窗口大小的两倍,并且您的 gl 视口需要与之匹配。

【讨论】:

我真正想知道的是,为什么retina屏幕坐标值是像素值的两倍? @JacksonZheng:这是 Apple 引入的一个 hack,以便遗留程序可以看到“正常”单位,让它们的窗口在实际以更高分辨率渲染时显示“正常”。说实话,这是一个导致各种问题的愚蠢黑客行为。但是人们会抱怨没有它阅读的程序看起来很小,销售量会下降,这是绝对不能发生的。技术敏感性很少会影响最终直接影响收入的决策。【参考方案2】:

帧缓冲区的大小永远不需要等于窗口的大小,因为你需要使用glfwGetFramebufferSize:

此函数检索指定窗口的帧缓冲区的大小(以像素为单位)。如果您希望检索屏幕坐标中的窗口大小,请参阅 glfwGetWindowSize。

每当您调整窗口大小时,您都需要检索其帧缓冲区的大小并根据它更新视口:

 glfwGetFramebufferSize(gWindow, &framebufferWidth, &framebufferHeight);

 glViewport(0, 0, framebufferWidth, framebufferHeight);

【讨论】:

【参考方案3】:

对于视网膜显示器,默认帧缓冲区(渲染到画布上的帧缓冲区)是显示器分辨率的两倍。因此,如果显示为 800x600,则内部画布为 1600x1200,因此您的 viewpoert 应为 1600x1200,因为这是进入帧缓冲区的“窗口”。

【讨论】:

以上是关于为啥retina屏幕坐标值是像素值的两倍的主要内容,如果未能解决你的问题,请参考以下文章

怎么从屏幕上读取任意一点的RGB值和坐标值?

屏幕适配

JS 获取屏幕中鼠标的坐标值

delphi中如何获得当前屏幕photoshop选择区域右上角的坐标值

移动端Retina屏幕1px边框问题

C#中,tagRECT结构的成员top、right、left、bottom代表啥?