我正在我的游戏引擎中使用自动 OpenGL 批处理方法,以减少绘制调用和冗余调用。
我的批处理树设计从最昂贵的状态开始,并为每个成本较低的状态添加叶子。
示例:树根:着色器/程序 兄弟:混合状态 ... aso
所以我的问题是最有可能是最昂贵的电话,在这个列表中:
- 绑定程序
- 结合纹理
- 绑定缓冲区
- 缓冲纹理、顶点数据
- 绑定渲染目标
- glEnable / glDisable
- 混合状态方程、颜色、函数、colorWriteMask
- 深度模板状态 depthFunc, stencilOperations, stencilFunction, writeMasks
还想知道哪种方法会更快:
- 将所有可批处理的绘制命令收集到单个顶点缓冲区并仅调用 1 个绘制调用(此方法还将强制在 cpu 端更新每个顶点的矩阵变换)
- 根本不进行批处理并渲染许多小绘制调用,只有批处理粒子系统...
PS:根据使用情况,渲染目标将始终更改为 Pre 或 Post。
目前进展:
- Andon M. Coleman:最便宜的统一和顶点数组绑定、昂贵的 FBO、纹理绑定
- datenwolf:程序使状态缓存无效
1:Framebuffer states
2:Program
3:Texture Binding
...
N:Vertex Array binding,Uniform binding
WebGL 中的当前执行树:
- 程序
- 属性指针
- 质地
- 混合状态
- 深度状态
- 模板正面/背面状态
- 光栅化器状态
- 采样器状态
- 绑定缓冲区
- 绘制数组
每个步骤都是一个兄弟哈希树,以避免再次检查主渲染队列中的状态缓存
加载纹理/程序/着色器/缓冲区在渲染之前发生在额外的队列中,以用于未来的多线程,并确保在对其进行任何操作之前初始化上下文。
自渲染对象的最大问题是您无法控制何时发生某些事情,例如如果开发人员在 gl 初始化之前调用这些方法,他不会知道为什么但他会遇到一些错误或问题......