金属镶嵌在细分的四边形上的处理方法

3

我对镶嵌技术完全陌生,对Metal API也比较新,一直在参考这个示例代码https://developer.apple.com/library/archive/samplecode/MetalBasicTessellation/Introduction/Intro.html

我意识到iOS上的最大镶嵌因子为16,与OSX上的64相比,对于我的用例来说非常低。我想我需要在一个已经被分成了4x4个小部分的四面体上应用镶嵌,这样在镶嵌之后,它将变成一个镶嵌因子为64的四面体?

所以,我已经将输入控制点更改为以下内容:

static const float controlPointPositionsQuad[] = {
    -0.8,  0.8, 0.0, 1.0,   // upper-left
     0.0,  0.8, 0.0, 1.0,   // upper-mid
     0.0,  0.0, 0.0, 1.0,   // mid-mid
    -0.8,  0.0, 0.0, 1.0,   // mid-left

    -0.8,  0.0, 0.0, 1.0,   // mid-left
     0.0,  0.0, 0.0, 1.0,   // mid-mid
     0.0, -0.8, 0.0, 1.0,   // lower-mid
    -0.8, -0.8, 0.0, 1.0,   // lower-left

     0.0,  0.8, 0.0, 1.0,   // upper-mid
     0.8,  0.8, 0.0, 1.0,   // upper-right
     0.8,  0.0, 0.0, 1.0,   // mid-right
     0.0,  0.0, 0.0, 1.0,   // mid-mid

     0.0,  0.0, 0.0, 1.0,   // mid-mid
     0.8,  0.0, 0.0, 1.0,   // mid-right
     0.8, -0.8, 0.0, 1.0,   // lower-right
     0.0, -0.8, 0.0, 1.0,   // lower-mid
};

我将drawPatches更改为16而不是4。 但结果是只显示了前4个点(左上角)。 如果我将顶点布局步长更改为以下内容:

vertexDescriptor.layouts[0].stride = 16*sizeof(float);

它仍然显示相同。

我不太清楚自己在做什么,但我想要的类似于将3D网格镶嵌,但对于我的情况只是一个细分的四边形。 我无法找到任何教授使用Metal API来实现这个功能的教程/代码示例。

请问有人能指点一下我吗?谢谢!


我认为您不需要更新缓冲区布局的步幅;除非您添加了更多的顶点属性,否则它应该保持为4 * sizeof(float)。您是否更新了调用dispatchThreadgroups以为新补丁生成镶嵌因子?您应该分派与补丁数量相同的线程。 - warrenm
好的 @warrenm,我尝试了这个[computeCommandEncoder dispatchThreadgroups:MTLSizeMake(2, 2, 1) threadsPerThreadgroup:MTLSizeMake(2, 2, 1)];但是我得到了这个错误 “失败的断言'component 1: 4必须<= 1对于pid [[thread_position_in_grid]]'” - Darren
我认为你想使用一个一维网格,即使这些补丁组成了一个二维晶格。尝试将每个大小的宽度设置为4,高度设置为1。 - warrenm
@warrenm 谢谢您的建议!这已经解决了错误,但是它仍然显示相同的内容。对于我的绘制命令,我是否做得正确? [renderCommandEncoder drawPatches:16 patchStart:0 patchCount:4 patchIndexBuffer:NULL patchIndexBufferOffset:0 instanceCount:1 baseInstance:0];或者顶点的顺序是错误的吗? - Darren
1
我认为你可能想交换 numberOfPatchControlPointspatchCount 参数。第一个参数表示每个补丁的控制点数量(在你的情况下可能是4),而 patchCount 参数确定要绘制的实际补丁数。 - warrenm
@warrenm 哇哦,太棒了!那就是这个谜题的答案!它起作用了!非常感谢你!如果可以的话,请写一个答案,我会将其标记为被接受的答案~ - Darren
1个回答

1

以下是一些需要检查的细节:

  1. 确保您的镶嵌系数计算内核为所有补丁生成内部/边缘系数,方法是执行相应大小的计算网格。
  2. 调用线程组以执行您的镶嵌系数内核时,请使用 1D 线程组计数和大小(总线程计数为补丁数,传递给分派方法的两个大小高度均为 1)。
  3. 在绘制补丁时,第一个参数 (numberOfPatchControlPoints) 应等于每个补丁中的控制点数(三角形为 3,四边形为 4)。第三个参数应为要绘制的补丁数。

有没有使用2D线程组的情况?例如,如果有200x200个要镶嵌的补丁,并且细分函数有点昂贵,那么通过调度200x200x1而不是40000x1x1,您可以获得性能优势吗? - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接