我最近一直致力于为Unity3d(like this)中由6个细分平面构成的球形行星生成网格数据。我在C#中创建了一个算法,让我在CPU上制作网格,为了学习目的,我决定使用计算着色器将此算法移植到GPU。虽然看起来所有顶点和法线都被正确计算,但是填充的三角形阵列最终变为半空,从而产生不希望的网格混乱。
由于我将行星上的每个平面视为2d顶点网格(即使它们被扭曲成球体),我通过在宽度和高度上循环来计算CPU上的三角形,采用由当前顶点及其后面和上方的3个顶点(左上角,右上角,左下角,当前顶点),并将适当的顶点索引分配给三角形数组。在GPU上我复制了我的代码几乎一行一行,因为语法非常相似,但似乎在某一点之后停止计算三角形。
为了测试它是否是三角形或顶点的错误,我用我用C#算法计算的三角形顶点索引覆盖了我的GPU计算三角形顶点索引。这给了我一个我想要的形状,表明这确实只是我三角形的一个问题。
CPU上生成的网格数据正确如下所示: Correct CPU implementation
从GPU生成错误的网格如下所示: Incorrect GPU implementation
CPU计算的三角形阵列和GPU计算的三角形阵列之间的差异可以在这个图像中看到,其中GPU在左侧,而CPU在右侧: Triangle array difference
我认为我的问题很可能是误解了计算着色器实际上如何执行线程计算/索引,但可能是我的实现存在问题。任何有助于理解为什么我的计算着色器实现失败的帮助都会帮助我。我在GitHub上包含了我的源代码链接,而不是在这里放置代码片段,因为它们可能难以理解。
CPU实施源代码:Source
GPU着色器调度程序源代码:Source
GPU计算着色器源代码:Source
答案 0 :(得分:1)
你刚刚用缓冲区计数做了一个简单的复制/粘贴错误:
ComputeBuffer vb = new ComputeBuffer (v.Length, 3 * sizeof(float)); //3 floats * 4 bytes / float
ComputeBuffer nb = new ComputeBuffer (n.Length, 3 * sizeof(float));
ComputeBuffer ub = new ComputeBuffer (n.Length, 2 * sizeof(float));
ComputeBuffer tb = new ComputeBuffer (n.Length, sizeof(int));
将其更改为此应该没问题:
ComputeBuffer vb = new ComputeBuffer (v.Length, 3 * sizeof(float)); //3 floats * 4 bytes / float
ComputeBuffer nb = new ComputeBuffer (n.Length, 3 * sizeof(float));
ComputeBuffer ub = new ComputeBuffer (u.Length, 2 * sizeof(float));
ComputeBuffer tb = new ComputeBuffer (t.Length, sizeof(int));