使用 Direct3D 绘制线列表时如何更改线的粗细?
这篇文章说不支持线宽并继续提供解决方法。其他选择?
当我们讨论这个话题时,着色器是否允许使用虚线图案绘制线条?
您可以使用几何着色器,将线段作为输入并输出四边形(由两个三角形组成的三角形条),以便四边形的宽度在屏幕空间中保持不变并与所需的线条粗细相匹配。它工作得非常好(因为在 CAD 3D 引擎中实现了它)。
如果几何着色器不是一个选项,解决方法可能是使用顶点着色器,但这需要对 VB 进行一些返工。请记住,VS 必须了解整个线段,因此您最终将为每个 VB 元素存储 p 和 p+1,加上索引/顶点重复的成本(取决于使用的拓扑和如果您将您的线渲染为索引图元)。
如果性能不是问题,那么在 CPU 上进行扩展可能是可行的方法。
编辑:
关于破折号模式:您也可以使用几何着色器来模拟glLineStipple
行为。如果您有GL_LINES
拓扑,即孤立的线,则模式会在每个新线段处重新开始。因此,您只需在几何着色器中计算线段的屏幕空间水平起点(或垂直起点,取决于方向),并将这些额外信息传递给像素着色器。然后像素着色器将负责根据因子和模式值丢弃片段(DirectX 10/11 整数和位指令使其变得容易)。
同样,这很好用,您可以将其与模拟宽度线结合使用(使用上面提到的第一种技术)。
现在,如果您有GL_LINE_STRIP
拓扑,则模式会在每个新图元处重新启动(因此对于每个新的绘图调用)。情况变得有点复杂,因为您需要了解之前已渲染的像素数,以及每个线段的像素数。
您可以通过使用 DirectX 10 流输出功能在临时 VB 中渲染线条来实现这一点(此 VB 的每个元素对应于每个段的屏幕空间长度)。然后你必须做这个VB的并行前缀和(又名扫描)(用于累积每个线段长度值)。
最后,你渲染你的线带,GL_LINES
但在 PS 中使用这个额外的 Scan VB 信息。
Direct3D 不仅不支持线条粗细,而且任何现有的 GPU 也不支持。我知道没有 GPU 甚至可以绘制正确的线(它们都是通过使用退化多边形来假线 - 也就是说,第二个和第三个顶点位于相同的位置,所以三角形基本上折叠成一条线)。
虽然可以在 OpenGL 中设置线宽,但 OpenGL 驱动程序会创建拉伸四边形(当前的 GPU 也不支持,并且为每个四边形使用两个三角形进行模拟)以在屏幕上绘制“线”。
因此,可能没有办法为此目的创建挤压四边形。正如 Stringer Bell 在他的回答中解释的那样,有几种方法可以实现这一目标。
对我来说最简单的方法是创建一个顶点缓冲区,其中包含每个顶点两次,法线指向“右”或“左”,具体取决于它们是线的右边缘还是左边缘。然后一个非常简单的顶点着色器可以执行挤压(通过将顶点位置更改为其法向量的倍数)。通过这种方式,您可以快速更改线宽,而无需在 CPU 上重新计算几何图形。如果您想根据对象的大小或距离调整线宽,这会很有用。
关于您的破折号图案(点画)问题,您最好的选择可能是将线渲染为细四边形并在像素着色器中对其应用纹理,其中纹理包含您的破折号图案。您需要将采样器地址模式设置为换行,例如:
SamplerState wrapTriLinear {
AddressU = WRAP;
AddressV = WRAP;
}