使用OpenGL(和OpenGL ES)渲染SVG

Mat*_*sch 55 opengl svg android opengl-es vector-graphics

我目前正在研究使用OpenGL和OpenGL ES从SVG文件渲染矢量图形的可能性.我打算以Windows和Android为目标.我理想的解决方案是拥有一个最小的C库,从给定的SVG文件生成多边形三角剖分.然后,这将生成标准的OpenGL或OpenGL ES调用,并在重绘时使用显示列表或vbo进行优化.我只需绘制一个显示列表,在翻译和旋转后绘制矢量图像,允许我将其与其他OpenGL调用混合.

到目前为止,我看到建议首先使用QT或开罗. - 这不是一个选项,因为我希望在没有膨胀库的情况下管理我自己的OpenGL上下文(在我想要实现的内容中).这也不适合Android.

第二个选项是使用渲染到纹理的库.虽然这可能适用于静态矢量图形,但对于经常进行缩放和旋转的游戏来说,它不是一种有效或可行的选择.

第三,有可能使用OpenVG.OpenVG规范(ShivaVG等)有一些开源实现,但我还没有找到一个能够在运行时从给定的SVG文件生成适当的OpenVG调用的库,我无法看到如何优化它我们可能希望使用显示列表或vbo.

这三种方法都受到限制.我认为最有希望的选择是在没有其他解决方案的情况下使用OpenVG实现.所以我的问题是,是否有任何图书馆可以做我想要的,或接近我想要的?如果没有,有什么理由不是吗?尝试从头开始这样做会更好吗?

zer*_*dog 12

在OpenGL ES之上查看MonkVG和OpenVG之类的API实现.

此外,对于OpenVG(MonkVG)结帐MonkSVG上的SVG渲染.

MonkVG专为iOS,OSX和Android平台而构建.

我是两个图书馆的作者,很乐意回答任何问题.


Fiz*_*izz 12

我的答案是关于通常使用OpenGL显示矢量图形,因为这个问题的所有解决方案都可以支持相当简单的SVG,尽管没有一个支持动画SVG(SMIL).由于没有关于动画的说法,我认为这个问题仅暗示静态SVG.

首先,我不会打扰任何OpenVG,甚至不使用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年提供了代码.)其中一位开罗开发者(也是英特尔员工)似乎也喜欢它http://lists.cairographics.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库的数量随着时间的推移而变得越来越多,我愚蠢地认为,使用一些主要供应商不支持的东西,你会大打赌.


小智 7

我目前正在研究使用OpenGL和OpenGL ES从SVG文件渲染矢量图形的可能性.我打算以Windows和Android为目标.我理想的解决方案是拥有一个最小的C库,从给定的SVG文件生成多边形三角剖分.然后,这将生成标准的OpenGL或OpenGL ES调用,并在重绘时使用显示列表或vbo进行优化.我只需绘制一个显示列表,在翻译和旋转后绘制矢量图像,允许我将其与其他OpenGL>调用混合.

如果你只想将SVG矢量形状转换为OpenGL | ES,那么我建议你自己做解析器和逻辑.请注意,SVG是一个巨大的规范,具有不同的功能,如绘制服务器(渐变,模式......),引用,过滤器,剪辑,字体处理,动画,脚本,链接等.

如果您需要完整的svg支持,那么http://code.google.com/p/enesim上有一个名为egueb(尤其是esvg)的库,它使用enesim(具有软件和opengl后端的渲染库)进行绘制.在大多数情况下,它使用着色器,并且所有内容都被渲染为纹理,库非常灵活,允许您适应您的特定需求,例如修改渲染场景,变换它等等.因为gl绘图总是在纹理中完成.

到目前为止,我看到建议首先使用QT或开罗. - 这不是一个选项,因为我希望在没有膨胀库的情况下管理我自己的OpenGL上下文(在我想要实现的内容中).这也不适合Android.

第二个选项是使用渲染到纹理的库.虽然这可能适用于静态矢量图形,但对于经常进行缩放和旋转的游戏来说,它不是一种有效或可行的选择.

在gl后端的特定情况下,enesim不会创建GLX(或任何其他窗口相关的上下文),您必须提供它,因此它完全适应您的情况,因为它只使用GL调用.

唯一的缺点是库在gl支持或完整的SVG规范支持方面尚未完成,但根据您的需要,在我看来似乎是一个不错的选择.


Cla*_*ery 6

需要说的是,使用OpenGL或OpenGL ES渲染SVG或OpenVG基本上是一个坏主意.OpenVG实施的原因很慢,而且很大程度上被放弃了.根据OpenGL的要求将路径细分(所有SVG/OpenVG渲染的基础)细分为三角形列表的过程基本上是缓慢且低效的.它基本上需要在3D渲染管道中插入排序/搜索算法,这会削弱性能.还存在需要动态存储器分配方案的问题,因为数据集的大小是未知的,因为SVG对路径几何的复杂性没有限制.一个非常差的设计.

SVG和OpenVG是由对现代3D图形硬件引擎实际工作原理(三角形列表)知之甚少的开发人员创建的.它们被创建为Adobe Flash的开放替代品,Adobe Flash也具有相同的有缺陷的体系结构,这使得Flash在行业中因不可预测的性能而受到谴责.

我的建议是重新考虑您的设计并直接使用OpenGL三角形列表.您可能需要编写更多代码,但您的应用程序的执行速度会提高一千倍以上,您可以比其他人更轻松地调试代码.


Cal*_*602 3

来自http://shivavg.svn.sourceforge.net/viewvc/shivavg/trunk/src/shPipeline.c?revision=14&view=markup

static void shDrawVertices(SHPath *p, GLenum mode)
{
int start = 0;
int size = 0;

/* We separate vertex arrays by contours to properly
handle the fill modes */
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, sizeof(SHVertex), p->vertices.items);

while (start < p->vertices.size) {
size = p->vertices.items[start].flags;
glDrawArrays(mode, start, size);
start += size;
}

glDisableClientState(GL_VERTEX_ARRAY);
}
Run Code Online (Sandbox Code Playgroud)

所以它确实使用了VBO。因此,我建议制作您自己的 SVG 解析器/使用预制的解析器,并将调用转发给 ShivaVG。

您仍然遇到 ShivaVG 使用 C(而不是 Java)并创建 opengl 上下文(而不是 opengles,如果我正确阅读代码)的问题。因此,即使您使用 Android 的 NDK 编译它,您也必须修改代码(例如,我见过一些 glVertex3f,但它们似乎不太需要......希望最好)。当然,另一个选择是将代码从 C 移植到 Java。也许没有你想象的那么痛苦。

祝你好运 !

  • 谢谢,我会研究一下这个。令我惊讶的是,考虑到对硬件加速矢量图形的需求以及 OpenVG 的设计考虑了移动设备这一事实,却没有一个开箱即用的实现。我知道一个用 C# 编写的项目尝试做一些非常类似的事情并取得成功的结果 [http://neuronspew.wordpress.com/category/svg-game-engine-project/](http://neuronspew.wordpress. com/category/svg-game-engine-project/)如果我能让这个工作正常的话,我一定会公开我的代码。 (2认同)