OpenGL ES 2引擎如何处理自动几何sorting和批处理?

我正在尝试编写一个基本的OpenGL ES 2引擎,可以自动对一组相当灵活的input绘制描述进行sorting和批处理

当我说“绘画描述”时,我的意思是实际的制服,状态,着色器等等,需要为由顶点/索引缓冲区描述的某些几何体发出一个绘制命令。

当我说“sorting”时,我的意思是命令一个绘制描述列表,以便不必要的状态变化最小化(即按表面sorting,然后着色,然后纹理等)

当我说“批处理”时,我特指通过合并多个共享相同绘制描述的顶点/索引缓冲区来合并绘制调用。

我试过了

看起来如果您可以对绘制描述列表进行sorting,您也可以进行批处理,因为您可以对绘制描述进行分组,比较相同。 所以我想我会创造一些像:

std::map<DrawDesc,std::vector<Geometry>,DrawDescComparator> 

std :: map对DrawDescs进行sorting,我可以在std :: vector中为相同的绘制描述存储几何。

但是,我在创建封装所有需要的信息的绘制描述对象时遇到了困难,并且特别允许将其进行比较。

有些东西很容易描述和比较,就像一个着色器可以分配一个唯一的ID。 其他事情变得复杂; 检查两个绘制描述之间的混合状态是否相同,在最坏的情况下,我必须查看(blend_enabled,equation_rgb,src_rgb,dst_rgb,equation_alpha,src_alpha,dst_alpha和blend_color):

 bool CompareBlendState(DrawDesc a, DrawDesc b) { if (!a.blend) return true; if (!b.blend) return false; if (a.equation_rgb != b.equation_rgb) // just use the underlying gl_enums for a consistent comparison return a.equation_rgb < b.equation_rgb; if (a.src_rgb != b.src_rgb) return a.src_rgb < b.src_rgb; //... if(a.etc != b.etc) return a.etc < b.etc; return false; } 

这可能是相当低效的。 使这个更好的一个可能的方式是将混合状态信息存储在std :: bitset中,并将相应的整数(s)

一般来说,我觉得我可能会在错误的树上咆哮。 有更多的状态比较(深度,剔除模式等),我不想创建一个难以维护的代码混乱。

我想知道其他引擎或库(统一,ue4等)如何处理这个问题,如果有一个共同的方法,我已经错过了。

你在做什么可能不是最有效的,但它仍然是相当有效率,简单,灵活和通常完成。 一个更高效,但代码更复杂,灵活性更低的解决scheme将是使用不同的绘图桶,根据所需的状态放置绘图,例如将不透明和透明网格分开。

我建议用你的方法将“绘制描述”打包成一个整数。 也不需要元组types(DrawDesc +几何vector),只需将几何graphicsid打包到该整数中(需要绘制的网格可以被认为是DrawDesc的一部分,对吗?)。

你应该把最昂贵的状态变化放到较高的位,最便宜的状态变化到较低的位。 然后,你可以简单地使用这个数字(简单的“大于”检查,没有分支,没有结构)对数据容器进行sorting。 所以你会得到一个粗略的scheme:

 typedef uint16_t DrawDesc; // may be 32 or 64 bits too) std::vector<DrawDesc> drawables; // put whatever info you need into this number, try to save bits. // here: 5 shader bits (32 shaders), 9 mesh bits (512 meshes) DrawDesc myDrawable = ((shaderID & 0x1f) << 9) | (meshID & 0x1ff); drawables.push_back(myDrawable); // Sort before drawing std::sort(drawables.begin(), drawables.end()); 

您现在可以迭代数据容器并计算可以批处理的连续元素(也可以在某处caching结果)。

可悲的是,std :: map是STL提供的最差的数据容器之一(内存分配可能会发生,而不是像caching一样友好,等等)。 但是使用这个解决scheme,你可以避免使用地图。