找出光栅化阶段后面向前(绘制)的多边形

时间:2013-12-28 10:16:07

标签: directx hlsl directx-11

我希望能够访问网格前面多边形的多边形id(PrimitiveID)。我只能在像素着色器中的光栅化器阶段之后看到这种情况。

我正在考虑创建一个追加缓冲区,但由于像素着色器被多次执行,它可能会多次追加相同的多边形ID。

我还想过创建一个数组布尔变量,并使用像素着色器中输入汇编程序阶段的原始id作为索引并将其设置为true,但是我必须首先将它们全部设置为false没有UAV缓冲区,除非我在那里遗漏了什么。

任何人都可以给我一些可能的解决方案。

编辑#1: 我正在为3D模型查看器实现“显示面法线”功能。我想只能在线框模式下看到绘制面的面法线。

编辑#2(可能的解决方案):现在我正试图用cuda或opencl来实现它。我想我不需要sv_primitiveId,如果我只是对观看截头音乐中的基元执行点积。这是Drop的回答。

1 个答案:

答案 0 :(得分:1)

"不止一种方法可以给猫皮肤" ;)

免责声明:我从未尝试过任何此类操作,甚至不确定它是否有效甚至可实施。只是想法,思考。

BTW,我仍然很好奇为什么你需要这个;)

  1. 在真正的硬件剪辑之前,你可以自己模仿背面剔除

    • 照常运行顶点和曲面细分着色器
    • 在几何着色器中(或在顶点着色器中,使用技巧)转换并遍历三角形
    • 计算相机视图方向和三角形平面法线
    • 之间的点积
    • If(dot> 0):将三角形附加到输出,if(dot< 0):不附加(剔除)
    • 如果在CPU端需要,可以读取流输出数据
    • 如果您需要知道确切传递了哪些基元以及哪些基元被剪裁,您可以以某种方式将SV_PrimitiveID添加到输出
    • 然后您可以在第二遍中继续渲染。您的几何图形已经转换,因此不需要预光栅化阶段。
    • 如果目标硬件支持多个流(Shader Model 5.0),则可以输出一个流到缓冲区(在CPU上读取)并光栅化第二个流。所以所有东西都是单程传递的。
  2. 使用像素着色器输出id的方法:

    • 如果在CPU端访问输出缓冲区,则可以对其进行排序,迭代,删除或忽略重复项。 std::vector + <algorithm>可以解决问题。
    • 如果你想继续使用GPU,你可以在着色器(像素或计算机)中做同样的事情,但这可能效率低下
    • 我认为,如果您想要与Shader Model 4兼容,可以使用整数纹理而不是结构化缓冲区。
    • 多个基元可以映射到单个像素。因此,您将不会获得不可见基元的索引,这些基元的像素在深度测试中被拒绝(如果基元与另一个完全重叠)。根据您的需要,这可能很重要。也许,您可以禁用深度测试并找出如何编写不同的
  3. 使用bool数组方法,您可能无法使用AppendStructuredBuffer,但如果您在渲染之前知道原始计数,则可以使用StructuredBuffer,用零初始化它并简单地写入它而不是追加。

  4. 当然,任何时候你都可以纯粹在CPU方面做到这一点。但那并不那么有趣。

  5. 由于评论而添加。哇,当你说&#34;在每个多边形面上画一些东西&#34;时,Nvidia DirectX 10 SDK中的SolidWireframe sample立即浮现在我脑海中。它是几何着色器的理想用法。基本上是:

    • 在GS中你可以为每个顶点提供texcoords,具体取决于它属于哪个面
    • 光栅化期间将发生硬件背面剔除
    • 在PS中你用那些texcoords来塑造你的脸部纹理
    • 作为替代方案,您可以 在顶点着色器中执行texcoords。您可以使用实例和SV_VertexIDSV_InstanceID进行欺骗:每个第一个顶点id,每个第二个顶点id,每个第三个顶点id。它会导致分支,但有希望在SM 3.0硬件上工作。
    • 极端情况:您可以预先计算离线设置顶点的替代texcoord。希望,一些3D编辑器,如3dsMax支持它。所以,根本不需要弄乱运行时。
  6. 希望它有所帮助。请留下评论,如果它会=)