一个格式化文本信息版面的小玩意
内容提要
文章介绍了作者在游戏引擎中使用imgui绘制调试信息界面的想法,并自己实现了一套新的文本信息排版的库。
延伸解读
从图形指令反推文本的局限
文章指出,imgui 输出的 draw list 只包含顶点数据流,丢失了原始绘图意图,例如文字变成两个三角形,箭头变成一个三角形。要在文本模式下重现这些图案,只能靠猜测三角形用途。imtui 库在这方面处理得并不理想,作者因此想到更廉价的猜测方案,但最终质疑这种反向解析的意义。
作者采用的文本识别技巧
作者模仿 imtui 实现新 backend 时,为字体定义特有 texture id,并将 ascii 码替换为 1x1 像素字模写入贴图。这样在 draw list 中发现文字绘制时,直接根据 uv 取字体贴图就能得到 ascii 码。相邻两个三角形若能构成矩形则视为背景框,非矩形三角形可判断箭头方向,复杂图形则直接丢弃。
方案转向与最终实现
完成 backend 测试后,作者怀疑让 imgui 输出三角形再反向解析的意义。他意识到自己并不需要完整可交互 UI,只是调试时展示信息,缺的是方便的版面编排接口。于是扔掉上午代码,下午重新实现了一套仅支持文本输出的排版库,借鉴 imgui 的 API 设计,几百行代码完成,并开源为 textcell。
Q&A
为什么作者想要用imgui来绘制调试信息界面?
因为游戏引擎中需要展示的信息越来越多,直接使用bgfx提供的调试文本输出API显得简陋,而imgui的API非常好用,尤其是table API可以方便地切分区块和安放控件。
bgfx自带的调试文本输出API有什么局限性?
bgfx提供的调试文本输出API非常简陋,只是提供了一个文本模式缓冲区,离控制台还很远,功能有限。
作者在寻找UI库时遇到了哪些问题?
作者先考虑基于ncursors的UI库,但没有找到喜欢的,且bgfx文本模式不是终端,可能需要先改造成VT100终端;后来发现imtui库项目不活跃,实现不理想,且imgui的绘图指令列表丢失了原始绘图意图,难以重现文本模式下的图案。
作者自己实现的imgui backend是如何识别文字绘制的?
作者为字体定义了一个特有的texture id,如果draw list里用到这个id,就认为是在绘制文字。然后使用自定义字形,把ascii码替换成1x1像素的字模,并写到贴图上,这样根据uv取字体贴图就能取到文本的ascii码。
作者最终为什么放弃imgui backend方案?
作者测试后对方案产生怀疑,认为让imgui输出一大堆三角形再反向解析回来没有多大意义,因为并不需要一个完整的可交互UI界面,只是为了调试时展示信息,之前不好用是因为没有方便的版面编排接口。
作者最终实现的文本信息排版库有什么特点?
作者最终实现了一个简单的文本信息排版库,只支持文本输出,API设计模仿了ImGui,具体实现几百行代码就搞定了,并开源在GitHub上(https://github.com/cloudwu/textcell)。