6

背景

使用 gluTess 从 GDI+ DrawString(..) 路径在 Direct3D9 中构建三角形列表:

镶嵌文本

然后使用像素着色器 (v3.0) 填充形状。使用不透明值进行绘制时,一切看起来都很好:

不透明的输出

问题

在某些字体大小下,如果颜色具有 alpha 分量(即 Argb #55FFFFFF),我们开始看到这些令人讨厌的曲面细分伪影,其中三角形可能会略微重叠:

透明输出

在较大的字体大小时,有时不存在问题:

大字体测试

使用 Intel 优秀的 GPA Frame Analyzer Pixel History 工具,我们可以看到在出现伪影的区域,像素已经从单个 Erg 中“触摸”了 3 次。

尔格分析

我试图弄清楚如何阻止我的像素着色器多次触摸同一个像素。

其他与防止过度绘制相关的解决方案似乎都是关于 zbuffer 策略的,但是这个问题更多地与在单个像素着色器通道中绘制单个 2D 三角形列表有关。

我在试图想出一个解决方案时有点不知所措。我希望 HLSL 可能有某种“每个像素只触摸一次”标志,但我一直找不到类似的东西。我发现最接近的是将 BLENDOP 设置为 MAX 而不是 ADD。但是当混合场景中的其他颜色时,输出不正确。

我也有 SRCBLEND = ONE,DSTBLEND = INVSRCALPHA。产生正确输出的唯一标志组合(尽管有过度绘制的工件。)

我在 GPA 帧分析器中使用过 SEPARATEALPHABLENDENABLE,这听起来几乎正是我在这里需要的——将混合设置为 MAX,但仅在“alpha”通道上,但据我所知,该设置(和相应的 BLENDOPALPHA)会影响什么都没有。

我想到的最后一件事是将不透明的文本烘焙到纹理上,然后使用适当的 alpha 值将该纹理重新绘制到场景中,但这实际上在这个项目中不起作用,因为我还支持渐变画笔,在哪里停止值可能包含 alpha,这意味着如果我们在烘焙到纹理之前将 alpha 从停止值中剥离出来,则仍然可以看到伪影,或者最终输出完全错误。此外,整个努力将非常昂贵。

任何提示或指针将不胜感激。谢谢阅读。

4

1 回答 1

1

你看到的问题不应该发生。

如果您的两个三角形重叠,那是因为您放置顶点的​​方式是在绘制相邻三角形时它们重叠。可能发生的情况是这两个相邻的三角形共享两个顶点,但是每个三角形都有自己的每个顶点的副本,这些副本被计算在一个非常非常细微的不同位置。

问题的解决方案不是尝试使像素着色器仅在使用索引缓冲区(如果您还没有)时才触摸像素,并且每个三角形之间的共享顶点实际上共享相同的顶点而不使用一个与相邻三角形使用的位置略有不同的位置。

如果您无法控制正在使用的曲面细分算法,则可能必须在生成顶点缓冲区后对其进行遍历,以检测和合并彼此之间的一些非常小的容差范围内的顶点。即使没有索引缓冲区,一个天真的解决方案是这样的:

  1. 对于顶点缓冲区中的每个顶点,将其位置与其余顶点缓冲区中的每个其他顶点进行比较。

  2. 如果两个顶点在另一个顶点的小公差范围内,请将第二个顶点的位置替换为您要与之比较的那个顶点的位置。

如果两个顶点的位置足够接近以至于您认为它们相同,这应该具有配对两个顶点的位置的效果。

你现在不应该对重叠的三角形有任何问题。在日常渲染中,两个三角形始终彼此共享边缘,您永远不会得到它们看起来几乎重叠的效果。硬件保证一个采样点要么在这条线的一侧,要么在另一侧,但绝不会同时在这两条线上,无论该点离这条线有多近(即使它在数学在线上,它仍然会失败一侧或另一侧)。

于 2013-12-21T17:20:52.933 回答