Direct3D线条粗细

时间:2010-02-17 11:11:38

标签: graphics directx direct3d shader

使用Direct3D绘制线列表时如何更改线条的粗细?

This post表示不支持行宽,并继续提供解决方法。其他选择?

虽然我们讨论这个主题,但着色器是否允许用虚线绘制线条?

4 个答案:

答案 0 :(得分:16)

您可以使用几何着色器将线条的一部分作为输入并输出四边形(由两个三角形组成的三角形条带),以便四边形的宽度在屏幕空间中保持不变并与所需线条匹配厚度。它非常适用(在CAD 3D引擎中实现它)。

如果几何着色器不是一个选项,解决方法可能是使用顶点着色器,但它需要重新编写VB。请记住,VS必须知道整个线段,因此您最终将为每个VB元素存储p和p + 1,以及索引/顶点重复的成本(取决于使用的拓扑和如果你将你的行渲染为索引基元而不是。)

如果性能不是问题,那么在CPU上进行扩展可能就好了。

编辑:

关于破折号模式:您也可以使用几何着色器来模拟glLineStipple行为。 如果您有GL_LINES拓扑,也就是隔离线,则模式会在每个新线段重新开始。因此,您只需在几何着色器中计算线段的屏幕空间水平起点(或垂直起点,取决于方向),并将此额外信息传递给像素着色器。然后,像素着色器将负责根据 factor pattern 值丢弃片段(DirectX 10/11整数和按位指令使其变得简单)。

再次这很好用,你可以将它与模拟宽度线组合(使用上面提到的第一种技术)。

现在,如果您有GL_LINE_STRIP拓扑,则模式将在每个新原语重新开始(因此对于每个新的绘制调用)。情况变得有点复杂,因为您需要知道之前渲染的像素数,以及每个线段的像素数。

使用DirectX 10流出功能在此临时VB中渲染线条可以实现这一点(此VB的每个元素对应于每个段的屏幕空间长度)。然后你必须做这个VB的并行前缀和(也就是扫描)(用于累积每个线段长度值)。

最后,您为GL_LINES渲染线条,但在PS中使用此额外的扫描VB信息。

答案 1 :(得分:15)

Direct3D不仅不支持线条粗细,也不支持任何当前存在的GPU。没有我知道的GPU甚至可以绘制正确的线条(它们都是通过使用退化多边形来假线 - 也就是说,第二个和第三个顶点位于相同的位置,因此三角形基本上折叠成一条线)。

虽然可以在OpenGL中设置线宽,但OpenGL驱动程序会创建拉伸四边形(当前GPU也不支持,并且每个四边形使用两个三角形进行模拟)以在屏幕上绘制“线条”

因此,可能无法为此目的创建挤压四边形。正如Stringer Bell在他的回答中所解释的那样,有几种方法可以实现这一目标。

对我来说最简单的方法是创建一个包含每个顶点两次的顶点缓冲区,法线指向“右”或“左”,具体取决于它们是行的右边缘还是左边缘。然后,一个非常简单的顶点着色器可以执行拉伸(通过将顶点位置改变其法线向量的倍数)。这样,您可以快速更改线宽,而无需在CPU上重新计算几何体。如果要根据对象的大小或距离调整线宽,这可能很有用。

答案 2 :(得分:2)

答案 3 :(得分:0)

关于你的破折号模式(点画)问题,你最好的选择可能是将线条渲染为一个薄的四边形并在像素着色器中应用一个纹理,其中纹理包含你的破折号模式。您需要将采样器地址模式设置为wrap,如:

SamplerState wrapTriLinear {
    AddressU = WRAP;
    AddressV = WRAP;
}