OpenGL:3D 中的粗线和 smooth/non-broken 线*
OpenGL : thick and smooth/non-broken lines *in 3D*
我有一个类似 3D CAD 的应用程序,我为此使用了 OpenGL 包装器库 (OpenSceneGraph)。对于应用程序,我正在尝试提出关于如何在 3D 中渲染 粗而平滑的线条的最佳策略。
又厚又滑我的意思是:
- 线宽可以大于OpenGL最大线宽值(在我的机器上好像是
10.f
)
- 在编写多段线时,我想避免 "broken lines" 的外观(参见下面的示例图片)
目前我使用 GL_LINE_STRIP_ADJACENCY
.
渲染折线
我发现有很多不同的资源可以介绍如何在 2D 中渲染漂亮的直线和曲线。不需要太多思考的最简单方法是将线渲染为一组四边形 (GL_QUAD_STRIP
)。这个解决方案的好处是它同时解决了我的两个问题。
例如,我还发现这个 nice library 可以实现范围广泛的直线和曲线外观。它使用三角形进行渲染。
注意:我不寻求像逐顶点着色或刷状笔触这样的奇特效果,只是一个 3D 线段,它可以有很大的厚度并且与另一条线段,它们之间没有任何间隙。
这些二维方法的问题是它们是二维的。当我改变视角时,很明显我的线几何图形不是线,而是位于某些 3D 平面中的 2D "ribbons"。我希望它们看起来像 3D 线条。
在思考这个问题时,我只能想出以下方法:
- 将线渲染为一组二维四边形(三角形),然后使它们始终面向相机
- 使用圆柱体等 3D 形状来表示线段
我不确定这两种解决方案的可行性如何(我是 OpenGL 的初学者)。我可能在现场有成百上千条多段线。我还想知道是否有更好、更聪明的方法来解决这个问题?我对任何事情都持开放态度,并且对最有效的方式感兴趣。谢谢。
编辑:正如用户@rickyviking 所指出的,我没有明确说明我正在追求 2D 外观(就像在任何类似 CAD 的应用程序中一样),这意味着: 线条的粗细不取决于 far/near 相机从它们的位置。
更新:感谢@rickyviking 的回答,我选择了使用几何着色器移动的方向。我仍然没有完整的解决方案,但可能 post 在获得结果时进行最终更新和最少的代码。
我不太了解它,但关于 NVidia's "path rendering" SDK (which was on the face of it just another one of those nice 2D libraries you're talking about) was that it actually put a bit of effort into interoperating with 3D. See the "Eureka: 3D Path Rendering!" section in this whitepaper 的许多有趣的事情之一。
曾经有人说它会成为标准的(非供应商特定的)OpenGL 扩展,但我不确定它是否发生过。
我以前使用过圆柱体,但那是一个需要真实世界尺寸的应用程序,需要在一行中改变尺寸,甚至改变颜色。
首先你需要弄清楚你想要的结果应该"look" 2D 还是 3D。
当您提到圆柱体时,它们肯定会产生“3D 效果”(距离 thinner/smaller 的几何体比靠近视点的几何体),但这不是类 CAD 应用程序通常的样子。
我相信您正在寻找 2D 外观结果,其中线条的宽度与它们与视点的距离无关。
使用库 like the one you mention 时,您应该在每次更改视点(可能是每一帧)时重新计算几何图形,以使它们始终面向屏幕平面。
另一种性能更好的方法是使用 "solid wireframe" 技术,这里是 an implementation from NVidia,它使用几何着色器(您可以在 OpenSceneGraph 中找到有关如何使用它们的几个示例)。
此处显示了其他类似技术:https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
我最终按照其中一个答案的建议使用了几何着色器。主要想法是将每条线段转换为三角形条带,并确保它始终面向相机并且厚度保持不变。
我还写了一个blog post about the implementation details. If someone finds it useful, I placed the shader codes on one of my github repos(该代码还提供了如何使用相同技术绘制粗而平滑的贝塞尔曲线的示例)。
下面是一些结果截图(绿线是用着色器画的,红线是用GL_LINE_STRIP_ADJACENCY
画的):
注意与绿色线相比,红线的相邻线段之间的间隙。
两条贝塞尔曲线(全部使用着色器绘制):
我有一个类似 3D CAD 的应用程序,我为此使用了 OpenGL 包装器库 (OpenSceneGraph)。对于应用程序,我正在尝试提出关于如何在 3D 中渲染 粗而平滑的线条的最佳策略。
又厚又滑我的意思是:
- 线宽可以大于OpenGL最大线宽值(在我的机器上好像是
10.f
) - 在编写多段线时,我想避免 "broken lines" 的外观(参见下面的示例图片)
目前我使用 GL_LINE_STRIP_ADJACENCY
.
我发现有很多不同的资源可以介绍如何在 2D 中渲染漂亮的直线和曲线。不需要太多思考的最简单方法是将线渲染为一组四边形 (GL_QUAD_STRIP
)。这个解决方案的好处是它同时解决了我的两个问题。
例如,我还发现这个 nice library 可以实现范围广泛的直线和曲线外观。它使用三角形进行渲染。
注意:我不寻求像逐顶点着色或刷状笔触这样的奇特效果,只是一个 3D 线段,它可以有很大的厚度并且与另一条线段,它们之间没有任何间隙。
这些二维方法的问题是它们是二维的。当我改变视角时,很明显我的线几何图形不是线,而是位于某些 3D 平面中的 2D "ribbons"。我希望它们看起来像 3D 线条。
在思考这个问题时,我只能想出以下方法:
- 将线渲染为一组二维四边形(三角形),然后使它们始终面向相机
- 使用圆柱体等 3D 形状来表示线段
我不确定这两种解决方案的可行性如何(我是 OpenGL 的初学者)。我可能在现场有成百上千条多段线。我还想知道是否有更好、更聪明的方法来解决这个问题?我对任何事情都持开放态度,并且对最有效的方式感兴趣。谢谢。
编辑:正如用户@rickyviking 所指出的,我没有明确说明我正在追求 2D 外观(就像在任何类似 CAD 的应用程序中一样),这意味着: 线条的粗细不取决于 far/near 相机从它们的位置。
更新:感谢@rickyviking 的回答,我选择了使用几何着色器移动的方向。我仍然没有完整的解决方案,但可能 post 在获得结果时进行最终更新和最少的代码。
我不太了解它,但关于 NVidia's "path rendering" SDK (which was on the face of it just another one of those nice 2D libraries you're talking about) was that it actually put a bit of effort into interoperating with 3D. See the "Eureka: 3D Path Rendering!" section in this whitepaper 的许多有趣的事情之一。
曾经有人说它会成为标准的(非供应商特定的)OpenGL 扩展,但我不确定它是否发生过。
我以前使用过圆柱体,但那是一个需要真实世界尺寸的应用程序,需要在一行中改变尺寸,甚至改变颜色。
首先你需要弄清楚你想要的结果应该"look" 2D 还是 3D。
当您提到圆柱体时,它们肯定会产生“3D 效果”(距离 thinner/smaller 的几何体比靠近视点的几何体),但这不是类 CAD 应用程序通常的样子。
我相信您正在寻找 2D 外观结果,其中线条的宽度与它们与视点的距离无关。
使用库 like the one you mention 时,您应该在每次更改视点(可能是每一帧)时重新计算几何图形,以使它们始终面向屏幕平面。
另一种性能更好的方法是使用 "solid wireframe" 技术,这里是 an implementation from NVidia,它使用几何着色器(您可以在 OpenSceneGraph 中找到有关如何使用它们的几个示例)。
此处显示了其他类似技术:https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader
我最终按照其中一个答案的建议使用了几何着色器。主要想法是将每条线段转换为三角形条带,并确保它始终面向相机并且厚度保持不变。
我还写了一个blog post about the implementation details. If someone finds it useful, I placed the shader codes on one of my github repos(该代码还提供了如何使用相同技术绘制粗而平滑的贝塞尔曲线的示例)。
下面是一些结果截图(绿线是用着色器画的,红线是用GL_LINE_STRIP_ADJACENCY
画的):
注意与绿色线相比,红线的相邻线段之间的间隙。
两条贝塞尔曲线(全部使用着色器绘制):