关于申请一个嗒啦啦认为可以开放的引擎功能。
06/0743 浏览BUG反馈 包含 AI 合成内容
所有内容由嗒啦啦编写。
功能申请:NanoVG 上下文独立离屏渲染(FBO 隔离)
申请内容
请求引擎为每个 NVG 上下文提供独立的离屏帧缓冲(FBO),最终按 renderOrder 合成到屏幕。
具体需求:
- 每个通过 nvgCreate() 创建的上下文,分配独立的离屏纹理(FBO)
- nvgBeginFrame 绑定到该上下文自己的 FBO(而非默认帧缓冲)
- nvgEndFrame 后,引擎按 renderOrder 从低到高,将每张纹理以 SOURCE_OVER 合成到屏幕
或者,提供等价的替代能力(如暴露 nvgluCreateFramebuffer 系列 API 到 Lua 层)。


项目背景
全量使用 NanoVG 矢量渲染的 2D 游戏项目,不使用引擎 3D/2D 渲染管线。
| 层级 | 技术 |
| 引擎 | UrhoX (Lua 5.4) |
| 渲染 | NanoVG 全量自绘 |
| 物理 | 自定义碰撞系统 |


遇到的障碍
问题描述
项目需要实现遮罩层多区域挖洞:在一个全屏黑色遮罩上,挖出多个可见区域(不规则多边形),这些区域可能互相重叠。
当前方案:画一个全屏黑色矩形,用 NVG_HOLE 挖出每个可见区域。
但 NanoVG 使用非零绕数填充规则——两个 HOLE 重叠时,该区域绕数变为 -2(而非 0),仍然被填充为黑色。视觉表现:重叠区域错误地显示为不透明。
为什么这个问题无法在代码层面解决
已尝试以下所有方案,均不可行:
| # | 方案 | 失败原因 |
| 1 | 多 HOLE 子路径 | 重叠区绕数 ≠ 0,被错误填充 |
| 2 | 桥接法合并路径 | 自交路径仍产生错误绕数 |
| 3 | 绕数修复(画 SOLID 补偿) | 需要非凸多边形交集 + 容斥原理 2^N 项,不可行 |
| 4 | 多边形并集(合并后画单洞) | Weiler-Atherton 算法过于复杂,且与凹多边形形态难以配合 |
| 5 | 多画布 + DESTINATION_OUT 擦洞 | 失败根因:多个 NVG 上下文共享帧缓冲,擦除操作穿透到底层 |
| 6 | 替代混合模式(XOR/LIGHTER 等) | 共享帧缓冲下无任何模式能实现"只擦本层" |
方案 5 的详细说明(最接近成功)
思路:创建三个 NVG 上下文,分层渲染。遮罩层用 DESTINATION_OUT 擦出可见区域——多个区域各自擦一次,不存在绕数问题。
vgBase (renderOrder=0) → 画场景内容
vgMask (renderOrder=50) → 铺黑 + DESTINATION_OUT 逐个擦出可见区域
vgTop (renderOrder=100)→ UI / HUD如果每个上下文有独立 FBO,DESTINATION_OUT 只擦 vgMask 自己的黑色填充,合成时透明区域自然透出底层内容。完美解决重叠问题。
实际测试发现:nvgSetRenderOrder 只控制绘制顺序,所有上下文共享同一块屏幕帧缓冲。DESTINATION_OUT 把底层 vgBase 的内容也一并擦除了。


为什么需要引擎支持
问题的本质
这是一个像素级合成问题:多个区域用布尔 OR(取最大值)合并透明度。主流游戏引擎(Unity RenderTexture、Unreal RenderTarget、Godot SubViewport)均通过"渲染到纹理 → 合成"解决此类问题。
NanoVG 原版开源库(nanovg_gl.h)提供了 nvgluCreateFramebuffer 用于离屏渲染,但 UrhoX 的 Lua 绑定未暴露此接口。
如果获得此能力
遮罩层的实现将变得简单直接:
- vgMask 在自己的 FBO 上铺黑
- 对每个可见区域多边形,用 DESTINATION_OUT 擦洞(互不干扰)
- 引擎合成时,vgMask 层的透明区域透出底层内容
无需复杂的多边形布尔运算,无绕数冲突,性能开销极低(一张额外纹理 + 一次合成 draw call)。
性能参考
离屏渲染是 GPU 的标准操作。对比:
- 普通 3D 游戏每帧使用数十个 FBO(阴影、反射、后处理)
- 本需求只需 1 个 FBO,内容为简单纯色多边形填充
- 性能影响可忽略


当前临时方案及其局限
针对上述问题,目前通过反转绘制顺序(从顶层往底层画)临时规避了 DESTINATION_OUT 穿透的问题——擦除时底层内容尚未绘制,因此不会被误伤。
但这是一个针对当前结构的特化方案,存在明确的架构风险:
- 脆弱性:绘制顺序被锁死为"上→下",后续新增任何上下文或渲染层,都可能再次触发同类冲突
- 扩展性差:如果未来需要更多独立混合操作的层(如模糊层、叠加特效层),同样无法隔离,相同问题会反复出现
- 根因未消除:多上下文共享帧缓冲这一限制仍然存在,项目架构建立在一个随时可能失效的绕过方案上
FBO 隔离是解决这一类问题的通用、稳定方案,而非仅为当前这一个场景服务。


补充信息
- 项目代码已改为多画布结构,可构建通过,随时可提供最小复现用例
- 如需技术沟通,随时配合
- 也接受等价替代方案(如暴露 nvgluCreateFramebuffer、或提供 NanoVG 渲染到 Texture2D 的能力)

