OpenGL:如何在3D中绘制粗细均匀、光滑/不断裂的线条

6
我有一个类似于3D CAD的应用程序,我使用OpenGL包装库(OpenSceneGraph)进行渲染。对于这个应用程序,我正在尝试找出如何在3D中呈现粗而平滑线条的最佳策略。
所谓的“粗而平滑”是指:
- 线条粗细可以超过OpenGL的最大线宽值(在我的机器上似乎是10.f) - 在组合折线时,我想避免出现“断裂线”的外观(请参见下面的示例图像)

OpenGL <code>LineStrip</code> looks broken, zoomed-in image

目前我使用GL_LINE_STRIP_ADJACENCY来渲染我的折线。

我发现有许多不同的资源可以教你如何在2D中渲染漂亮的线条和曲线。最简单的方法是将线渲染为一组四边形(GL_QUAD_STRIP),这种方法不需要太多思考。这种解决方案的好处是它同时解决了我的两个问题。

例如,我还找到了这个nice library,它可以实现各种各样的线条和曲线外观。它使用三角形进行渲染。

注意:我不寻求像每个顶点着色或类似刷子的笔画之类的花哨效果,只需要一个可以具有大厚度的3D线段,并且与另一个线段连接良好,它们之间没有任何间隙。

问题是这些2D方法都是2D的。当我改变视角时,显然我的线几何体不是线而是位于某些3D平面上的2D“带状物”。而我想让它们看起来像3D线条。

思考这个问题时,我只能想到以下方法
  1. 将线渲染为一组2D四边形(三角形),然后使它们始终面向相机
  2. 使用某些3D形状(如圆柱体)来表示线段
我不确定这两种解决方案中的任何一种是否可行(我是OpenGL的初学者)。场景中可能会有数百甚至数千个折线。我也在想是否有更好、更聪明的方法来解决这个问题?我对任何事情都持开放态度,并对最有效的方式感兴趣。谢谢。 编辑: 正如用户@rickyviking所指出的那样,我没有明确说明我正在寻求一个二维外观(就像在任何类CAD应用程序中一样),这意味着:线条的厚度不取决于相机距离它们的远近。 更新: 感谢@rickyviking的答案,我选择了几何着色器的方向。我还没有完整的解决方案,但当结果实现时,可能会在此处发布最终更新和最小代码。
4个回答

11

我最终使用了几何着色器,正如其中一篇答案所建议的那样。主要思路是将每条线段转换为三角形带,并确保它始终面向相机且厚度保持不变。

我还写了一篇博客文章详细介绍了实现细节。如果有人觉得有用,我将着色器代码放在了我的Github仓库之一上(该代码还提供了如何使用相同技术绘制粗糙和平滑的贝塞尔曲线的示例)。

以下是一些结果截图(绿色线条使用着色器绘制,红色线条使用GL_LINE_STRIP_ADJACENCY绘制):

same thickness example

bigger thickness example

请注意红色线段与绿色线段之间的间隔。
两条贝塞尔曲线(均使用着色器绘制):

Bezier curve examples


1
谢谢,非常有用 :) - Tom

3
首先,您需要澄清自己想要的结果是“看起来”2D还是3D。当提到圆柱体时,它们肯定会有“3D效果”(远离视点的几何形状比靠近视点的几何形状更薄/更小),但这不是类似CAD的应用程序通常的外观。
我认为您想要一个看起来像2D的结果,在这种情况下,您的线条宽度与它们距离视点的距离无关。使用类似您提到的库时,应每次更改视点(可能每帧)重新计算几何形状,以使其始终面向屏幕平面。
一种替代且性能更好的方法是使用“实心线框”技术,这里有来自NVidia的一个实现(链接),它使用几何着色器(您可以在OpenSceneGraph中找到几个使用它们的示例)。 其他类似的技术在这里展示:(链接)

+1,这些是非常相关的观点。你说得对,我正在追求2D外观效果。我会在那些链接上多读一些。 - vicrucann
链接的问题在于它们随着时间的推移会失效。 - Adrian Maire

1
我对此并不了解太多,但NVidia的“路径渲染”SDK是许多有趣事物之一(表面上仅是你所说的另一个不错的2D库),它实际上花了一些精力与3D互操作。请参阅本白皮书中的“尤里卡:3D路径渲染!”部分。
曾经有传言称它将成为标准(非供应商特定)的OpenGL扩展,但我不确定它是否真正发生过。

0

我以前用过圆柱体,但那是一个需要实际真实尺寸、一行中不同大小甚至颜色变化的应用程序。


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