web-dev-qa-db-fra.com

Rendu SVG avec OpenGL (et OpenGL ES)

J'étudie actuellement la possibilité de rendre des graphiques vectoriels à partir d'un fichier SVG en utilisant OpenGL et OpenGL ES. J'ai l'intention de cibler Windows et Android. Ma solution idéale serait d'avoir une bibliothèque C minimale qui génère une triangulation de polygone à partir d'un fichier SVG donné. Cela générerait alors des appels OpenGL ou OpenGL ES standard et utiliserait une liste d'affichage ou un vbo pour l'optimisation lors du redessin. Je voudrais simplement dessiner une liste d'affichage pour dessiner l'image vectorielle après la traduction et la rotation, ce qui me permet de mélanger cela avec d'autres appels OpenGL.

Jusqu'à présent, je vois que les suggestions sont d'utiliser d'abord QT ou Cairo. - Ce n'est pas une option étant donné que je souhaite gérer mon propre contexte OpenGL sans bibliothèques gonflées (dans le contexte de ce que j'essaie de réaliser). Cela ne convient pas non plus à Android.

La deuxième option consiste à utiliser des bibliothèques qui rendent une texture. Bien que cela puisse être correct pour les graphiques vectoriels statiques, ce n'est pas une option efficace ou faisable pour les jeux où la mise à l'échelle et les rotations se produisent fréquemment.

Troisièmement, il est possible d'utiliser OpenVG. Il existe des implémentations open source de la spécification OpenVG (ShivaVG, etc.), mais je n'ai pas encore trouvé de bibliothèque capable de générer les appels OpenVG appropriés à partir d'un fichier SVG donné au moment de l'exécution, et je ne vois pas comment optimiser cela en tant que nous pourrions souhaiter avec une liste d'affichage ou vbo.

Les trois méthodes souffrent de limitations. Je pense que l'option la plus prometteuse est d'utiliser une implémentation OpenVG si aucune autre solution n'existe. Ma question est donc la suivante: y a-t-il des bibliothèques qui font ce que je veux ou près de ce que je veux? Sinon, y a-t-il une bonne raison pour laquelle non? Et serait-il préférable d'essayer de le faire à partir de zéro?

54
Matt Esch

De 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);
}

Il utilise donc un VBO. Je suggère donc de créer votre propre analyseur SVG/d'utiliser un préfabriqué et de transférer les appels vers ShivaVG.

Vous avez toujours le problème que ShivaVG est en C (et non en Java) et crée un contexte opengl (et non opengles, si j'ai lu le code correctement). Donc, même si vous le compilez à l'aide du NDK d'Android, vous devrez modifier le code (par exemple, j'ai vu quelques glVertex3f autour, mais ils ne semblent pas être très nécessaires ... espérons le meilleur). L'autre option, bien sûr, c'est de porter le code de C vers Java. Peut-être pas aussi douloureux que vous pourriez l'imaginer.

Bonne chance !

3
Calvin1602

Découvrez MonkVG une implémentation d'API de type OpenVG au-dessus d'OpenGL ES.

En outre, pour le rendu SVG au-dessus de la caisse OpenVG (MonkVG) MonkSVG .

MonkVG a été conçu pour les plates-formes iOS, OSX et Android.

Je suis l'auteur des deux bibliothèques et serais heureux de répondre à toutes vos questions.

12
zerodog

Ma réponse va à propos de l'affichage de graphiques vectoriels avec OpenGL en général, car toutes les solutions à ce problème peuvent prendre en charge de manière plutôt triviale SVG en particulier, bien qu'aucune ne prenne en charge les SVG animés (SMIL). Puisqu'il n'y avait rien dit à propos de l'animation, je suppose que la question impliquait uniquement les SVG statiques.

Tout d'abord, je ne m'embêterais pas avec quoi que ce soit d'OpenVG, pas même avec MonkVG, qui est probablement la mise en œuvre la plus moderne, quoique incomplète. Le comité OpenVG a fermé ses portes en 2011 et la plupart sinon toutes les implémentations sont des abandons de logiciels ou, au mieux, des logiciels hérités.

Depuis 2011, l'état de l'art est le bébé de Mark Kilgard, NV_path_rendering , qui n'est actuellement qu'une extension de fournisseur (Nvidia) comme vous l'avez peut-être déjà deviné son nom. Il y a beaucoup de documents là-dessus:

Vous pouvez bien sûr charger des SVG et autres https://www.youtube.com/watch?v=bCrohG6PJQE . Ils prennent également en charge la syntaxe PostScript pour les chemins. Vous pouvez également mélanger le rendu de chemin avec d'autres éléments OpenGL (3D), comme le montre:

NV_path_rendering est désormais utilisé par la bibliothèque Skia de Google dans les coulisses, lorsqu'il est disponible. (Nvidia a contribué au code fin 2013 et 2014.) L'un des développeurs du Caire (qui est également un employé d'Intel) semble l'aimer aussi http://lists.cairographics.org/archives/cairo/2013 -March/024134.html , bien que je ne sois pas [encore] au courant d'efforts concrets pour que le Caire utilise NV_path_rendering.

NV_path_rendering a quelques dépendances mineures sur le pipeline fixe, il peut donc être un peu gênant à utiliser dans OpenGL ES. Ce problème documenté dans le document d'extension officiel lié ci-dessus. Pour une solution de contournement, voyez par exemple ce que Skia/Chromium a fait: https://code.google.com/p/chromium/issues/detail?id=3443

Un parvenu ayant encore moins (ou carrément pas) de soutien aux fournisseurs ou de paillettes académiques est NanoVG , qui est actuellement développé et maintenu. ( https://github.com/memononen/nanovg ) Étant donné le nombre de bibliothèques 2D sur OpenGL qui sont apparues et disparues au fil du temps, vous faites un gros pari en utilisant quelque chose qui n'est pas pris en charge par un majeur vendeur, à mon humble avis.

12
Fizz

Il faut dire que le rendu SVG ou OpenVG avec OpenGL ou OpenGL ES est fondamentalement une mauvaise idée. Il y a des raisons pour lesquelles les implémentations d'OpenVG sont toutes si lentes et largement abandonnées. Le processus de pavage des chemins (la base de tout rendu SVG/OpenVG) en listes de triangles comme requis par OpenGL est fondamentalement lent et inefficace. Cela nécessite essentiellement l'insertion d'un algorithme de tri/recherche dans le pipeline de rendu 3D, ce qui paralyse les performances. Il y a aussi le problème qu'un schéma d'allocation de mémoire dynamique est nécessaire car la taille de l'ensemble de données est inconnue car SVG ne limite pas la complexité de la géométrie du chemin. Un design vraiment médiocre.

SVG et OpenVG ont été créés par des développeurs qui comprenaient peu le fonctionnement réel des moteurs matériels graphiques 3D modernes (listes triangulaires). Ils ont été créés pour être une alternative ouverte à Adobe Flash, qui a également la même architecture défectueuse qui a rendu Flash vilipendé dans l'industrie pour des performances imprévisibles.

Mon conseil est de repenser votre conception et d'utiliser directement les listes de triangles OpenGL. Vous devrez peut-être écrire plus de code, mais votre application fonctionnera environ mille fois mieux et vous pourrez plus facilement déboguer votre code que quelqu'un d'autre.

7
ClayMontgomery

J'étudie actuellement la possibilité de rendre des graphiques vectoriels à partir d'un fichier SVG> en utilisant OpenGL et OpenGL ES. J'ai l'intention de cibler Windows et Android. Ma solution idéale serait d'avoir une bibliothèque C minimale qui génère une triangulation de polygone à partir d'un fichier SVG donné. Cela générerait alors des appels OpenGL ou OpenGL ES standard et utiliserait une liste d'affichage ou un vbo pour l'optimisation lors du redessin. Je voudrais simplement dessiner une liste d'affichage pour dessiner l'image vectorielle après la traduction et la rotation, ce qui me permet de mélanger cela avec d'autres appels OpenGL>.

Si vous souhaitez uniquement transformer des formes vectorielles SVG en OpenGL | ES, je vous suggère de faire l'analyseur et la logique vous-même. Notez que SVG est une énorme spécification, avec différentes fonctionnalités telles que les serveurs Paint (dégradés, motifs ...), les références, les filtres, l'écrêtage, la gestion des polices, les animations, les scripts, les liens, etc., etc.

Si vous voulez un support svg complet, alors il y a une bibliothèque sur http://code.google.com/p/enesim appelée egueb (et en particulier esvg) qui utilise enesim (une bibliothèque de rendu qui a un logiciel et opengl backends) pour le dessin. Dans la plupart des cas, il utilise des shaders et tout est rendu dans une texture, la bibliothèque est très flexible vous permettant de vous adapter à vos besoins particuliers comme la modification de la scène rendue, sa transformation, etc. Parce que le dessin gl est toujours fait en texture.

Jusqu'à présent, je vois que les suggestions sont d'utiliser d'abord QT ou Cairo. - Ce n'est pas une option étant donné que je souhaite gérer mon propre contexte OpenGL sans bibliothèques gonflées (dans le contexte de ce que j'essaie de réaliser). Cela ne convient pas non plus à Android.

La deuxième option consiste à utiliser des bibliothèques qui rendent une texture. Bien que cela puisse être correct pour les graphiques vectoriels statiques, ce n'est pas une option efficace ou faisable pour les jeux où la mise à l'échelle et les rotations se produisent fréquemment.

Dans le cas particulier du backend gl, enesim ne crée pas de GLX (ou tout autre contexte dépendant de la fenêtre), vous devez le fournir, donc il s'adapte parfaitement à votre situation car il utilise uniquement GL = appels.

Le seul inconvénient est que la bibliothèque n'est pas encore complète en termes de support gl ou de support complet des spécifications SVG, mais selon vos besoins, cela me semble être une bonne option.

7
turran

Vous pouvez jeter un œil à AmanithVG , ils semblent avoir mis en place un bon chemin -> pipeline de triangles. J'ai essayé l'exemple iOS GL tiger, et il semble que la triangulation ne soit pas un véritable goulot d'étranglement.

1
mirknac