在OpenGL中显示SVG而无需中间光栅化

28
我有一些简单的SVG艺术品(图标和字符等),我想在一个OpenGL应用程序中显示它们(在Debian上使用C++开发,使用Qt)。
显而易见的解决方案是使用ImageMagick库SVG转换为光栅图像,并将其贴图到适当的多边形上(或者只是使用传统的glDrawPixels)。
但是,我想知道是否有什么东西可以直接将SVG转换为一系列的OpenGL调用,并使用OpenGL的线条、多边形等进行渲染。有人知道能做到这一点的吗?

2
嗯...当涉及到贝塞尔曲线时,问题有点棘手。如果能看到一个解决方案就好了,因为这两种技术相互补充得很好。 - SpliFF
还有一种可能性是使用tkzinc。 - chris
1
这个问题已经在https://dev59.com/eG015IYBdhLWcg3w9wp1上再次被提出。 - Fizz
5个回答

13

Qt可以做到这一点。
QSvgRenderer可以将SVG绘制在QGLWidget上。
如果您想在QGLWidget上除了SVG之外再绘制其他内容,可能需要对paintEvent()进行微调。


谢谢,非常有趣(我自己应该注意到那个)。从文档中不清楚QPainter-on-QGLWidget是否完全保留了向量方面,还是会发生一些中间光栅化。不过使用GLintercept/GLtrace应该很容易找出来... - timday
QPainter通常不进行任何光栅化操作。在SVG的情况下,它没有理由开始这样做。 - shoosh
在我的平台上,我已经成功将GLTrace与Qt4应用程序配合使用(简单的修复,已发送给作者),我可以确认SVG正在使用大量的gl *调用在GLWidget上绘制。Trolltech在http://doc.trolltech.com/4.4/opengl-overpainting.html提供了一个很好的将2D和3D世界结合起来的示例。我唯一能想象到的进一步操作是在GL显示列表中捕获SVG渲染调用(尽管这样做的唯一原因是性能,如果这成为问题,我更有可能缓存渲染位图)。 - timday
我会使用错误报告网页表单发送一个功能请求。 - shoosh
我还注意到,在Nvidia驱动程序中启用自动多重采样也使SVG图形看起来非常漂亮和抗锯齿(如果Qt只是将一些软件渲染的位图贴图,这种效果是不会出现的)。 - timday

5

SVGL 似乎可以解决这个问题,但已经停滞了数年。尽管如此,您可能仍然能够在那里找到一些有价值的代码。


下面“dru”提到的“sauvage”项目似乎是继承者。同一作者,但使用的是Python而不是C ++。 - timday

2
我的答案将涉及OpenGL中显示矢量图形的一般方法,因为所有这个问题的解决方案都可以相对容易地支持特定的SVG,尽管没有一个支持动画SVG(SMIL)。由于没有提到动画,我假设问题只涉及静态SVG。
自2011年以来,最先进的技术是Mark Kilgard的“NV_path_rendering”,目前仅是供应商(Nvidia)扩展,从名称上就可以猜到了。有很多相关材料: 当然,您可以加载SVG等文件https://www.youtube.com/watch?v=bCrohG6PJQE。它们还支持路径的PostScript语法。您还可以将路径渲染与其他OpenGL(3D)内容混合使用,如演示的那样: NV_path_rendering现在被Google的Skia库在后台使用(如果可用)。 (Nvidia在2013年末和2014年贡献了代码。)其中一个cairo开发人员(也是英特尔员工)似乎也喜欢它http://lists.cairographics.org/archives/cairo/2013-March/024134.html,尽管我还不知道cairo是否有任何具体的努力来使用NV_path_rendering。
一个新兴的、甚至没有或根本没有供应商支持或学术光环的2D图形库是NanoVG,目前正在开发和维护中。(https://github.com/memononen/nanovg)考虑到随着时间的推移,已经出现并消失的许多OpenGL 2D库,我认为如果使用某些不受主要供应商支持的东西,你会冒很大的风险。

2
看起来Inkscape有一些有趣的导出选项,您可能会发现它们很有用。它们包括DXF、PovRay、EPS、PS(PostScript)、XAML、Latex和OpenDocument Drawing(ODG)。也许其中一个有转换器,您可以使用Inkscape作为中介。
DXF特别适合,因为它已经是常见的3D格式。assimp是加载DXF的好选择。

Inkscape目前还没有完整的SVG实现,因此我想它的导出选项也是部分的。 - shoosh
其实我使用的所有SVG都是在Inkscape中创建的,只要它能够导出自己的所有内容...没问题。 - timday
1
你的限制更多地与输出格式有关,而不是SVG。DXF已经存在了数百万年,它不会支持裁剪标记或复杂的渐变色。 - SpliFF

1
我制作了一个名为Omber的矢量绘图程序,它有一定的能力导入SVG文件,并且可以将矢量图形导出为“扁平化”的glTF 2.0格式3D模型。glTF格式基本上只是原始的OpenGL数据,因此您可以使用最少的代码读取并显示它。我编写了一个小的Pixi.js插件,用于使用WebGL显示包含矢量艺术的glTF文件。
Blender也支持导入SVG文件。然后,您可以将结果导出为3D文件格式,但是Blender对SVG的支持更多地用于导入简单的曲线而不是复杂的绘图。
我相信还有其他工具也可以做这样的事情。一个问题是,SVG早于现代图形硬件,因此其许多功能在OpenGL中实现起来非常麻烦,特别是以高效的方式。诸如组的不透明度、不规则形状的渐变、基于光栅的滤镜操作等等都可能变得混乱,因此我不确定能够将SVG的更奇特的功能通常受到转换为3D格式的程序的支持。

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