跳转到内容
菜单
← 返回博客

修复 Nova UI 在 WebGL 中的 8K 文本问题

Frustrated developer comparing broken glyph rows in the browser console and Unity Editor.

要点

  • 现象:文本超过约 260 个字符时,出现错误字形,但仅发生在 WebGL 上。
  • 原因:Nova 的回退渲染器将顶点打包到一维 RGBA 纹理中,宽度超过了 WebGL 的 8192 像素限制。
  • 修复:将缓冲区分成宽度为 8192 像素的行,并同步 shader 中的行宽。

问题:长文本显示损坏

测试发现,WebGL 中超过约 260 chars ≈ 1 024 glyphs 的对话文本,会大约每隔 20 个字形丢失或替换字符。Editor 中原本正常,直到我们强制启用 SystemSettings.UseFallbackRendering = true,同样的问题才出现。

// WebGL console
Texture has out of range width (got 12800 max supported 8192)

原因:过大的回退缓冲区与行宽不一致

当 SSBO 不可用时,例如 WebGL,Nova 会通过纹理缓冲区进行回退渲染。每个字形顶点占 64 字节,即四个 float4 像素。一个包含 3224 个顶点的 <TextBlock> 会生成 12896 px × 1 的纹理,远超 WebGL 限制。

把宽度限制到 8192 像素后,又出现了第二个问题:shader 仍然预期每行宽 16384 像素,导致更新写入一行,而 GPU 从另一行读取。

通过两处代码调整解决

1. 将缓冲区纹理分行

int maxEdge = 8192;
int width   = Mathf.Min(numPixels, maxEdge);
int height  = Mathf.CeilToInt((float)numPixels / width);
texture = new Texture2D(width, height, TextureFormat.RGBAFloat, false, true);

2. 同步 shader 常量

#if defined(NOVA_FALLBACK_RENDERING)
  #if defined(UNITY_WEBGL) || defined(UNITY_EDITOR)
    #define MAX_TEXTURE_DIMENSION 8192u
  #else
    #define MAX_TEXTURE_DIMENSION 16384u
  #endif
#endif

我们还修改了 SetData(),让 RGBA 路径遵循 shaderBufferStartIndex * 4,避免运行时更新覆盖之前的字形。

结果

  • WebGL 构建:没有显示伪影或崩溃。
  • 独立桌面构建继续使用 16384 像素的 SSBO 路径。
  • Editor 中仍有异常表现,但目前并非优先修复事项。

下一步

改动位于 develop 分支,预计会随下一次 Alpha 版本发布。如果你遇到类似的 Nova UI 问题,欢迎通过 Discord、Facebook 或评论告诉我们。

Leave a Comment

Scroll to Top