在GPU上创建共享的顶点法线


9

我已经成功地将Marching Cubes的实现从CPU移植到了OpenGL计算着色器中,但是我还没有解决法线问题,并且想知道最好的解决方法。

我的实现专门处理二进制值字段(我正在尝试为尚没有距离估计器的3D分形函数建模),因此渐变和前向差分方法将不起作用。我有共享的顶点在工作,并且我的CPU实现使用此处描述的Quilez方法将面法线累积到每个相邻顶点上。

我可以将该实现移植到另一个着色器上,但是我看到的问题是需要大量的原子。由于我们只能在标量整数类型上使用原子,并且我无法想到一种以可加方式将3个有符号的int打包为1的方法,这意味着每个着色器调用3个轴* 3个顶点= 9个原子加法。它们当然会散布在整个内存中,所以这不像是击中单个原子计数器9次,但它看起来仍然像是个地狱。

另一种选择是针对每个多边形运行一个着色器调用,并构建人脸法线列表(我可能会以此方式打包到x10y10z10),然后每个顶点的着色器来累积所有相邻人脸的法线。但是,这将是一个巨大的内存消耗,面部索引的存储空间每个顶点需要12 int才能处理最坏的情况。还有一个问题,如何在不再次使用原子的情况下写入该存储,以计算出已将多少张面写入特定顶点。

任何人对此有更好的主意吗?

Answers:


5

对于仅nVidia的解决方案,您可以使用浮点原子添加内部函数(例如NvInterlockedAddFp32)来解锁HLSL中的GPU内部函数。NVIDIA开发人员

我在80.000个顶点网格上进行了尝试,而且速度非常快(如果我没记错的话,在GTX980M上大约是1或2毫秒)

只是要注意在发行版中编译着色器以使内部函数起作用(由于nvidia错误/限制)

同样要当心顶点分裂(例如由于UV不连续),您必须处理它们,否则在UV接缝处会有多余的硬边。


因为问题很旧,所以我会问你:-)我所理解的仅仅是,每个顶点都有邻接信息不足以胜任鲁斯?
Andreas

这是去年为我的论文项目准备的,最终我只用了愚蠢的方法,使用了整数原子加法,按比例放大以最大化精度,然后将其归一化为浮点向量。无法找到一种方法来列出每个顶点周围的面,而又不分配最坏情况的空间并使用原子计数器来构建列表。它可能像地狱般效率低下,但是从CPU版本和一流的标记来看,我仍然获得了几个数量级的提速,因此我对此非常满意:)
russ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.