闪烁的插入符号通常是如何实现的?

How are blinking carets often implemented?

我正在尝试实现一个跨平台的 UI 库,它占用的系统资源越少越好。我正在考虑使用我自己的软件渲染器或 opengl。

对于固定控件,一切都很好,我可以仅在需要时重新绘制。然而,在实现动画时,尤其是像 sublime text 中的 'phase' 插入符号这样的动画闪烁插入符号时,我看不到一种平衡资源使用和性能的简单方法。

对于闪烁的插入符号,需要非常频繁地重新绘制插入符号(我猜至少每秒 15-20 次)。一方面,软件渲染器支持部分重绘但速度太慢而不实用(大型重绘区域为 3-4 fps,例如 1000x800,这使得无法实现动画)。另一方面,据我所知,opengl 不支持部分重绘,这意味着整个屏幕需要以 15-20 fps 不断渲染。

所以我的问题是:

  1. 插入符通常如何在各种 UI 系统中实现?
  2. 有没有办法让opengl只渲染到屏幕的一部分?
    • 我知道 glViewport 可以渲染部分屏幕,但由于双缓冲或其他原因,屏幕的其余部分无法保持原样。这样我还需要重新渲染整个屏幕

首先你需要问问自己。 我真的需要部分重绘屏幕吗?

OpenGL 或更好的说法是 GPU 可以轻松绘制数千个三角形。因此,在开始摆弄屏幕的部分重绘之前,您应该改为进行基准测试,看看它是否值得研究。

但这并不意味着您必须无休止地重绘屏幕。您仍然可以在发生更改时重新绘制它。

因此,如果您的光标每 500 毫秒闪烁一次,那么您每 500 毫秒重绘一次。如果您有一个动画 运行,那么您会在播放该动画时不断地重绘(或者每次动画进行需要重绘的更改时)。

这就是 Chrome、Firefox 等所做的。如果您打开开发人员工具 (F12) 并转到“时间轴”选项卡,您可以看到这一点。

看看下面的截图。时间轴的第一行显示 Chrome 重绘 windows.

的频率
  • 第一节显示了很多连续重绘。 这是因为我在页面上滚动。
  • 最后一部分显示每 500 毫秒重绘一次。 光标在文本框中闪烁。

在新标签页中打开图片,以更好地查看发生了什么。

请注意,它不会说明 Chrome 是完全重绘 window 还是仅重绘其中的一部分。它只是显示重绘的频率。 (如果你想看到重新绘制的区域,那么 Firefox 和 Chrome 都有“显示绘制矩形”。

绕过双缓冲和部分重绘的问题。然后你可以改为绘制到帧缓冲区对象。现在您可以随心所欲地使用 glScissor()。如果你有各种静态的东西,只有少数动态的东西。然后你可以有多个帧缓冲区对象,只绘制一次静态内容并不断更新包含动态内容的帧缓冲区。

但是(我怎么强调都不为过)进行基准测试并检查是否需要这样做。拥有两个帧缓冲区对象可能比总是重绘所有内容更昂贵。与将所有矩形打包在一个缓冲区中相比,每个矩形都有一个缓冲区也是如此。

最后举个例子让我们举个例子NanoGUI (a minimalistic GUI library for OpenGL)。 NanoGUI 不断重绘屏幕。 问题只是 连续重绘屏幕是现在您需要一个系统来发出重绘。现在在标签上调用 setText() 需要回调并告诉 window 重绘。现在,如果标签添加到的父面板不可见怎么办?然后setText()刚刚发出了屏幕的冗余重绘。

我想表达的意思是,如果您有一个用于发布屏幕重绘的系统。那可能更容易出错。因此,除非连续重绘是一个问题,否则这绝对是一个更优化的起点。