使用 OpenGL(和 OpenGL ES)渲染 SVG
我目前正在研究使用 OpenGL 和 OpenGL ES 从 SVG 文件渲染矢量图形的可能性。我打算针对 Windows 和 Android。我理想的解决方案是拥有一个最小的 C 库,可以从给定的 SVG 文件生成多边形三角剖分。然后,这将生成标准 OpenGL 或 OpenGL ES 调用,并在重绘时使用显示列表或 vbo 进行优化。我只需绘制一个显示列表来绘制平移和旋转后的矢量图像,从而允许我将其与其他 OpenGL 调用混合。
到目前为止我看到的建议是首先使用QT或Cairo。 - 这不是一个选项,因为我希望在没有臃肿库的情况下管理自己的 OpenGL 上下文(在我想要实现的上下文中)。这也不适合 Android。
第二个选项是使用渲染到纹理的库。虽然这对于静态矢量图形来说可能没问题,但对于经常发生缩放和旋转的游戏来说,这不是一个有效或可行的选择。
第三,可以使用OpenVG。 OpenVG 规范有一些开源实现(ShivaVG 等),但我还没有找到一个能够在运行时从给定的 SVG 文件生成适当的 OpenVG 调用的库,而且我不知道如何优化它:我们可能希望使用显示列表或 vbo。
所有这三种方法都存在局限性。我认为如果没有其他解决方案存在,最有希望的选择是使用 OpenVG 实现。所以我的问题是,是否有任何库可以满足我的需求,或者接近我想要的功能?如果没有,是否有充分的理由不这样做?尝试从头开始做这件事会更好吗?
I am currently investigating the possibility of rendering vector graphics from an SVG file using OpenGL and OpenGL ES. I intend to target Windows and Android. My ideal solution would be to have a minimal C library that generates a polygon triangulation from a given SVG file. This would then generate standard OpenGL or OpenGL ES calls, and use a display list or vbo for optimization when redrawing. I would simply draw a display list to draw the vector image after translating and rotating, allowing me to mix this with other OpenGL calls.
So far I see that the suggestions are to firstly use QT or Cairo. - This is not an option given that I wish to manage my own OpenGL context without bloated libraries (in the context of what I am trying to achieve). Nor is this suitable for Android.
Second option is to use libraries that render to a texture. While this might be ok for static vector graphics, it's not an efficient or feasible option for games where scaling and rotations occur frequently.
Thirdly there is the possibility of using OpenVG. There are some opensource implementations of the OpenVG specification (ShivaVG etc), but I am yet to find a library that is capable of generating the appropriate OpenVG calls from a given SVG file at runtime, and I can't see how to optimize this as we might wish to with a display list or vbo.
All three methods suffer limitations. I think the most promising option is using an OpenVG implementation if no other solution exists. So my question is, are there any libraries out there that do what I want, or close to what I want? If not, is there a good reason why not? And would it be better to attempt to do this from the ground up instead?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我的答案是关于使用 OpenGL 显示矢量图形,因为这个问题的所有解决方案都可以支持相当普通的 SVG,尽管没有一个支持动画 SVG (SMIL)。由于没有提及动画,我认为这个问题仅暗示静态 SVG。
首先,我不会为任何 OpenVG 烦恼,甚至不会为 MonkVG 烦恼,MonkVG 可能是最现代的,尽管不完整的实现。 OpenVG 委员会已于 2011 年解散,大多数(如果不是全部)实现都是废弃软件或最多是遗留软件。
自 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.cairgraphics.org/archives/cairo/2013-March/024134.html,尽管我[还]不知道 cairo 使用 NV_path_rendering 的任何具体努力。
NV_path_rendering 对固定管道有一些小的依赖性,因此在 OpenGL ES 中使用它可能有点麻烦。此问题记录在上面链接的官方扩展文档中。有关解决方法,请参阅 Skia/Chromium 所做的示例:https:// code.google.com/p/chromium/issues/detail?id=344330
一个拥有更少(或完全没有)供应商支持或学术浮华的新贵是 NanoVG,它目前正在开发和维护。 (https://github.com/memononen/nanovg) 考虑到 OpenGL 上的 2D 库的数量随着时间的推移,你正在冒很大的赌注,使用不受主要供应商支持的东西,以我的拙见。
My answer is going to about displaying vector graphics wtih OpenGL in general, because all solutions for this problem can support rather trivially SVG in particular, although none support animated SVGs (SMIL). Since there was nothing said about animation, I assume the question implied static SVGs only.
First, I would not bother with anything OpenVG, not even with MonkVG, which is probably the most modern, albeit incomplete implementation. The OpenVG committee has folded in 2011 and most if not all implementations are abandonware or at best legacy software.
Since 2011, the state of the art is Mark Kilgard's baby, NV_path_rendering, which is currently only a vendor (Nvidia) extension as you might have guessed already from its name. There are a lot of materials on that:
You can of course load SVGs and such https://www.youtube.com/watch?v=bCrohG6PJQE. They also support the PostScript syntax for paths. You can also mix path rendering with other OpenGL (3D) stuff, as demoed at:
NV_path_rendering is now used by Google's Skia library behind the scenes, when available. (Nvidia contributed the code in late 2013 and 2014.) One of the cairo devs (who is an Intel employee as well) seems to like it too http://lists.cairographics.org/archives/cairo/2013-March/024134.html, although I'm not [yet] aware of any concrete efforts for cairo to use NV_path_rendering.
NV_path_rendering has some minor dependencies on the fixed pipeline, so it can a bit of nuisance to use in OpenGL ES. This issue documented in the official extension doc linked above. For a workaround see for example what Skia/Chromium has done: https://code.google.com/p/chromium/issues/detail?id=344330
An upstart having even less (or downright no) vendor support or academic glitz is NanoVG, which is currently developed and maintained. (https://github.com/memononen/nanovg) Given the number of 2D libraries over OpenGL that have come and gone over time, you're taking a big bet using something not supported by a major vendor, in my humble opinion.
查看 MonkVG 一个基于 OpenGL ES 的类似 OpenVG 的 API 实现。
另外,对于 OpenVG (MonkVG) 之上的 SVG 渲染,请查看 MonkSVG。
MonkVG 是为 iOS、OSX 和 Android 平台构建的。
我是这两个库的作者,很乐意回答任何问题。
Check out MonkVG an OpenVG like API implementation on top of OpenGL ES.
Also, for SVG rendering on top of OpenVG (MonkVG) checkout MonkSVG.
MonkVG has been built for iOS, OSX, and Android platforms.
I'm the author of both libraries and would be happy to answer any questions.
需要指出的是,使用 OpenGL 或 OpenGL ES 渲染 SVG 或 OpenVG 从根本上来说是一个坏主意。 OpenVG 的实现如此缓慢并且大部分被放弃是有原因的。按照 OpenGL 的要求将路径(所有 SVG/OpenVG 渲染的基础)细分为三角形列表的过程从根本上来说是缓慢且低效的。它基本上需要在 3D 渲染管道中插入排序/搜索算法,这会削弱性能。还有一个问题是需要动态内存分配方案,因为数据集的大小是未知的,因为 SVG 对路径几何的复杂性没有限制。一个非常糟糕的设计。
SVG 和 OpenVG 是由对现代 3D 图形硬件引擎实际工作原理(三角形列表)知之甚少的开发人员创建的。它们被创建为 Adobe Flash 的开放替代品,而 Adobe Flash 也具有相同的有缺陷的架构,这使得 Flash 因其不可预测的性能而在业界受到诟病。
我的建议是重新考虑你的设计并直接使用 OpenGL 三角形列表。您可能需要编写更多代码,但您的应用程序的性能将提高大约一千倍,并且您可以比其他人更轻松地调试您的代码。
It needs to be said that rendering SVG or OpenVG with OpenGL or OpenGL ES is fundamentally a bad idea. There are reasons the OpenVG implementations are all so slow and largely abandoned. The process of tessellating paths (the foundation of all SVG/OpenVG rendering) into triangle lists as required by OpenGL is fundamentally slow and inefficient. It basically requires inserting a sort/search algorithm into the 3D rendering pipeline, which cripples performance. There is also the problem that a dynamic memory allocation scheme is required because the size of the data set is unknown since SVG places no limits on the complexity of the path geometry. A really poor design.
SVG and OpenVG were created by developers who had little understanding of how modern 3D graphics hardware engines actually work (triangle lists). They were created to be an open alternative to Adobe Flash, which also has the same flawed architecture that has made Flash reviled in the industry for unpredictable performance.
My advice is to rethink your design and use OpenGL triangle lists directly. You may have to write more code, but your app will perform about a thousand times better and you can more easily debug your code than someone elses.
如果您只想将 SVG 矢量形状转换为 OpenGL|ES,那么我建议您自己完成解析器和逻辑。请注意,SVG 是一个庞大的规范,具有不同的功能,例如绘画服务器(渐变、图案...)、引用、过滤器、剪辑、字体处理、动画、脚本、链接等。
如果您想要完整的 svg 支持,那么http://code.google.com/p/enesim 上有一个名为 egueb(尤其是 esvg)的库,它使用enesim(渲染库有用于绘图的软件和 opengl 后端)。在大多数情况下,它使用着色器并且所有内容都渲染为纹理,该库非常灵活,允许您适应您的特定需求,例如修改渲染的场景、对其进行转换等。因为 gl 绘制始终是在纹理中完成的。
在 gl 后端的特定情况下,enesim 不会创建 GLX(或任何其他窗口相关上下文),您必须提供它,因此它完全适合您的情况,因为它只使用 GL 调用。
唯一的缺点是该库在 gl 支持或完整的 SVG 规范支持方面尚不完整,但根据您的需求,在我看来这是一个不错的选择。
If you only want to transform SVG vector shapes into OpenGL|ES, then I suggest to do the parser and the logic yourself. Note that SVG is a huge spec, with different features like paint servers (gradients, patterns ...), references, filters, clipping, font handling, animations, scripting, linking, etc, etc.
If you want full svg support, then there's a library on http://code.google.com/p/enesim called egueb (and particularly esvg) which uses enesim (a rendering library that has software and opengl backends) for the drawing. In most cases it uses shaders and everything is rendered into a texture, the library is very flexible allowing you to adapt to your particular needs like modifying the rendered scene, transform it, etc. Because the gl drawing is done always into a texture.
In the particular case of the gl backend, enesim does not create a GLX (or any other window dependent context), you have to provide it, so it adapts perfectly to your situation as it only uses GL calls.
The only drawback is that the library is not complete yet in terms of gl support or full SVG spec support, but depending on your needs, seems to me like a good option.
来自 http://shivavg。 svn.sourceforge.net/viewvc/shivavg/trunk/src/shPipeline.c?revision=14&view=markup :
所以它确实使用了VBO。因此,我建议制作您自己的 SVG 解析器/使用预制的解析器,并将调用转发给 ShivaVG。
您仍然遇到 ShivaVG 使用 C(而不是 Java)并创建 opengl 上下文(而不是 opengles,如果我正确阅读代码的话)的问题。因此,即使您使用 Android 的 NDK 编译它,您也必须修改代码(例如,我见过一些 glVertex3f,但它们似乎不太需要......希望最好)。当然,另一个选择是将代码从 C 移植到 Java。也许没有你想象的那么痛苦。
祝你好运 !
From http://shivavg.svn.sourceforge.net/viewvc/shivavg/trunk/src/shPipeline.c?revision=14&view=markup :
So it does use a VBO. So I'd suggest making your own SVG parser / use a pre-made one, and forward the calls to ShivaVG.
You still have the problem that ShivaVG is in C (and not in Java) and creates an opengl context (and not opengles, if I read the code correctly). So even if you compile it using Android's NDK, you'll have to modify the code ( for instance, I've seen a few glVertex3f around, but they don't seem to be much needed... hope for the best). The other option, of course, it to port the code from C to Java. Maybe not as painful as you could imagine.
Good luck !
你可以看看 AmanithVG,他们似乎实现了一个很好的路径 ->三角形管道。我已经尝试过 iOS GL Tiger 示例,看来三角测量并不是真正的瓶颈。
You can have a look at AmanithVG, they seem to have implemented a good paths -> triangles pipeline. I've tried the iOS GL tiger example, and it seems that triangulation is not a real bottleneck.