Rendering SVG with OpenGL (and OpenGL ES) - android

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?

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:
https://developer.nvidia.com/nv-path-rendering Nvidia hub, but some material on the landing page is not the most up-to-date
http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/opengl/gpupathrender.pdf Siggraph 2012 paper
http://on-demand.gputechconf.com/gtc/2014/presentations/S4810-accelerating-vector-graphics-mobile-web.pdf GTC 2014 presentation
http://www.opengl.org/registry/specs/NV/path_rendering.txt official extension doc
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:
https://www.youtube.com/watch?v=FVYl4o1rgIs
https://www.youtube.com/watch?v=yZBXGLlmg2U
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.

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.

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.

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.
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.
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.
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.

From 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);
}
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 !

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.

Related

What is the best tool for 3D model environment for Android Studio

I'm trying to create to create an app that will house a 3D sphere, with a surface color skin, that the user will be able to manipulate (rotate, zoom in/zoom out, be able to drop pins on coordinates, & other simple tasks like that). I was first considering using OpenGL ES, but I'm currently scared by the following comment taken from https://developer.android.com/guide/topics/graphics/opengl.html,
"However, if you want more control of what your application draws on screen, or are venturing into three dimensional graphics, you need to use a different tool."
Is 3D modeling a complete waste of time in OpenGL ES? Am I better off with a different tool?
Thanks for the help!
First, page you have linked does not have the quoted text. It´s instead in this text.
Now, about the text itself: you are taking it out of context and/or misunderstanding it. Here's a full citation:
The Android framework provides plenty of
standard tools for creating attractive, functional
graphical user interfaces. However, if you want
more control of what your application draws on
screen, or are venturing into three dimensional
graphics, you need to use a different tool. The
OpenGL ES APIs provided by the Android
framework offers a set of tools for displaying
high-end, animated graphics that are limited only
by your imagination and can also benefit from the
acceleration of graphics processing units (GPUs)
provided on many Android devices.
Which means that Android provides standard tools (Canvas or views), but for more control or 3D graphics you need to use OpenGL ES.
Is 3D modeling a complete waste of time in
OpenGL ES? Am I better off with a different tool?
OpenGL ES and the recent Vulkan API are the only tools available for Android which let you do 3D graphics and use GPU more directly.
So, OpenGL ES is what you should use (or Vulkan, if the devices you are targetting have support for it).
OpenGL ES is just a low-level accelerated rendering API - it will let your application get pretty pixels on to the screen.
All of the higher-level logic (handling rotate, zoom, pins, deciding what to draw, etc) needs to be provided by your application. OpenGL ES provides the tools to help, but it can't provide the logic for you.

Canvas or OpenGL ES2 for Android 2D game?

OK, so I just got this idea for a game. I already know how to develop for Android, so I though of developing for Android first.
The game (without revealing too much :D) will have a single shape onscreen all the time. It will have to smoothly change shape, color etc. in response to a few knobs/sliders on the screen.
As we do not have multiple shapes/objects I do not need any form of physics engine now. I need to be able to draw polygons and transition colors/gradients effortlessly. I'm targeting a high FPS for this game (think PewPew/2Fuse!)
Do I need OpenGL for this? If so, where can I learn it?
(I'm aware that OpenGL is difficult, and that it's time-consuming to learn.)
I can only offer some of my views. Programming a game is much about transferring artistic assets from the programs, in which they are created (3D modeling programs, Photoshop, Gimp, ...), into your own program. Whether you select OpenGL or Canvas is therefore somewhat dependent upon the nature of your assets (3D models, or bitmaps only, for example). You should be aware however, that on modern Android devices OpenGL ES support is universal and that on those devices the Canvas is implemented with OpenGL ES. Choosing OpenGL ES therefore eliminates one level of indirection. You also have libraries like Cocos2D that offer 2D APIs, but use OpenGL for implementation. To conclude, without top-notch artistic assets your game cannot succeed, if those are good however, even a game using the Canvas may succeed.
EDIT: I think you should proceed like this:
game design -> assets implementing game design -> API offering the shortest path towards the reproduction of the assets in your game
If your assets are polygon based (as you mention in a comment) you should go with OpenGL ES 2.0. OpenGL ES 2.0 is non-trivial to learn, but in learning it, you would gain some marketable skills and experience, and you could make work that is very "showy" for a programmer. Just be patient and try to understand how it works and not just "slop through it."
A great place to start learning is with a tutorial like this one.

OpenGL ES or android.graphics?

I'm developing a client for LBS service and I need to implement some 2D and 3D graphics.
As I read, standard package android.graphics is better for 2D grahics and drawing simple objects, and opengl es is better for 3D and it works faster. Unfortunatelly, I did'n find anything alse about their differences. Does anybody konow more about differences between drawing with OpenGL ES and with android.graphics?
OpenGL will give you full control over the graphics that you are using. You will not have many limitations long term on what you would like to do. You can make a good 3D game on an Android using OpenGL, as you can render large amounts of polys and overlay 2D graphics on top of those. It is a great deal of work, though.
Regular old OpenGL is my favorite, and I'd hate to have to use any of the frameworks mentioned in other answers, but I've been working with 3D graphics for many years. I can see why others would recommend them.
If you haven't done 3D graphics before, you have a steep learning curve in front of you. If you don't take the time to learn the underlying math and rendering concepts, you will struggle with it long term.
I love the reference pages from Khronos
Also, the Android developer site has some nice reference.
The main difference is that OpenGL is much faster compared to Canvas (The Android 2D graphics drawing surface). Although hardware acceleration is enabled for Canvas since honeycomb, it is a bit tricky to use it effectively.
Canvas does make life easier though. It's easy to use and simple to understand even for someone new to Computer Graphics.
In the end it will depend on what you need to do. If you need the fancy stuff like Geometry, Lighting etc then you should definitely go for OpenGL. Besides, If you need 3D then OpenGL is your only option since Canvas only supports 2D graphics.
Bare bones OpenGL is very tedious to use in my opinion so I would suggest a framework such as the ones mentioned here.
Hope this helps.

Optimizing the OpenGL ES settings for 2D drawing

I'm experimenting with using OpenGL ES to draw rather complicated paths, as I was running into severe performance problems when using the generic Android drawing functions. So far using OpenGL directly seems to be significantly faster, but I'm wondering about the difference between drawing in 2D as compared to 3D.
I'm using the example from the Google Tutorial on OpenGL, and modified it a bit to remove the third dimension from my vertices. Just omitting the z coordinate in glVertexAttribPointer and passing 2 as the size parameter seems to work. This seems to be an obvious and easy optimization, and it also makes the code a bit clearer. But I'm wondering at which other places OpenGL ES just assumes 3D, and does unnecessary work.
For example, I don't need any depth testing, but from what I read it isn't clear to me if just never explicitly enabling it is enough, or if I need to disable any settings?
I'm not looking for microoptimizations, but for general settings that remove assumptions that I'm working in 3D and simplify or remove calculations that just are not necessary in 2D. What are other things I should do when I'm working in pure 2D, and not in 3D?

Android: Deciding between SurfaceView and OpenGL (GLSurfaceView)

Is there a way to decide up front based on the expected complexity of a game/app in the planning phase whether to use regular Canvas drawing in a SurfaceView or to go with OpenGL?
I've been playing around with a Canvas and only need 2D movement, and on a fairly new phone I'm getting pretty decent performance with a bunch of primitive objects and a few bitmaps running around the screen on a solid background.
Is it fair to say that if I'm going to be drawing background images and increasing the number of objects being moved and drawn on top of them that I should go straight to OpenGL?
All I can say is that it depends on how many sprites you're gonna use. Chris Pruett from Google has also documented this part very well.
Google I/O 2009 and Google I/O 2010.
Below is a picture from one of his slides that are related to your topic:
With that knowledge, you should go with OpenGL using the draw_texture extension. Remember to query out the string and check if draw_texture is supported on the actual device.
For further information that are related to game development in general, see this.
SurfaceView
A GLSurfaceView is a SurfaceView that you can render into with OpenGL.
Choosing between them is simple:
If you're familiar with OpenGL and need what it provides, use a
GLSurfaceView. Otherwise, use a SurfaceView. OpenGL is low-level. If
you're not already familiar with it, it's an undertaking to learn. If
you only need 2D drawing, SurfaceView uses the high-level, reasonably
high-performance Canvas. It's very easy to work with.
Unless you have a strong reason to use a GLSurfaceView, you should use
a regular SurfaceView. I would suggest that if you don't already know
that you need GL, then you probably don't.
OpenGL
OpenGL would be able to handle the rotations and scaling easily.
Honestly, you would probably need to learn a lot of OpenGL to do this,
specifically related to the topics of:
Geometry Lighting (or just disabling it) Picking (selecting geometry
to draw on it) Pixel Maps Texture Mapping Mipmapping Also, learning
OpenGL for this might be overkill, and you would have to be pretty
good at it to make it efficient.
Instead, I would recommend using the graphic components of a game
library built on top of openGL, such as:
Cocos2d
libgdx
Any of the engines listed here
Source
Difference between SurfaceView and GLSurfaceView in Android
Android: Canvas vs OpenGL

Categories

Resources