55 votes

Rendu de 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 polygonale à partir d'un fichier SVG donné. Cela générerait ensuite des appels OpenGL ou OpenGL ES standard, et utiliserait une liste d'affichage ou un vbo pour l'optimisation lors du redessin. J'utiliserais simplement une liste d'affichage pour dessiner l'image vectorielle après la translation et la rotation, ce qui me permettrait 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 d'accomplir). Ce n'est pas non plus adapté à Android.

La deuxième option consiste à utiliser des bibliothèques qui effectuent un rendu sur une texture. Si cela peut convenir pour des graphiques vectoriels statiques, ce n'est pas une option efficace ou réalisable pour les jeux où les mises à l'échelle et les rotations sont fréquentes.

Troisièmement, il y a la possibilité d'utiliser OpenVG. Il y a quelques implémentations opensource 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 comme on pourrait le faire avec une liste d'affichage ou un vbo.

Ces trois méthodes présentent des limites. 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 : existe-t-il des bibliothèques qui font ce que je veux, ou qui s'en rapprochent ? Si ce n'est pas le cas, y a-t-il une bonne raison de ne pas le faire ? Et serait-il préférable d'essayer de le faire à partir de zéro ?

12voto

micahp Points 426

Vérifiez MonkVG une mise en œuvre de l'API de type OpenVG au-dessus d'OpenGL ES.

De même, pour le rendu SVG au-dessus d'OpenVG (MonkVG), vérifiez les données suivantes MonkSVG .

MonkVG a été conçu pour les plateformes iOS, OSX et Android.

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

12voto

user3588161 Points 305

Ma réponse va porter sur l'affichage de graphiques vectoriels avec OpenGL en général, parce que toutes les solutions à ce problème peuvent supporter assez trivialement les SVG en particulier, bien qu'aucune ne supporte les SVG animés (SMIL). Puisque rien n'a été dit sur l'animation, je suppose que la question impliquait uniquement les SVG statiques.

Premièrement, je ne m'embêterais pas avec quoi que ce soit d'OpenVG, pas même avec MonkVG, qui est probablement l'implémentation la plus moderne, bien qu'incomplète. Le comité OpenVG a été dissous en 2011 et la plupart des implémentations, sinon toutes, sont des logiciels abandonnés 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 du fournisseur (Nvidia), comme vous l'avez peut-être déjà deviné d'après son nom. Il existe de nombreux documents à ce sujet :

Vous pouvez bien sûr charger des SVG et d'autres éléments. 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 chemins avec d'autres fonctions OpenGL (3D), comme le montre la démonstration :

NV_path_rendering est maintenant utilisé par la bibliothèque Skia de Google dans les coulisses, lorsqu'elle est disponible. (Nvidia a contribué au code à la fin de 2013 et en 2014.) L'un des développeurs du Caire (qui est également un employé d'Intel) semble également l'apprécier. 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 est documenté dans le document officiel de l'extension dont le lien figure ci-dessus. Pour une solution de contournement, voir par exemple ce que Skia/Chromium a fait : https://code.google.com/p/chromium/issues/detail?id=344330

Un nouveau venu ayant encore moins (ou carrément pas) de soutien de la part des fournisseurs ou de prestige académique est NanoVG qui est actuellement développé et entretenu. ( https://github.com/memononen/nanovg ) Étant donné le nombre de bibliothèques 2D sur OpenGL qui sont apparues et ont disparu au fil du temps, vous prenez un gros pari en utilisant quelque chose qui n'est pas supporté par un fournisseur majeur, à mon humble avis.

7voto

turran Points 41

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 idéale serait d'avoir une bibliothèque C minimale qui génère une triangulation polygonale à partir d'un fichier fichier SVG donné. Cela génèrerait ensuite des appels OpenGL ou OpenGL ES standard, et utiliserait une liste d'affichage ou un vbo pour l'optimisation lorsque le rouge est présent. ou vbo pour l'optimisation lors du redessin. J'utiliserais simplement une liste d'affichage pour dessiner l'image vectorielle après la translation et la rotation, ce qui me permettrait de mélanger cela avec d'autres appels OpenGL >.

Si vous voulez seulement transformer des formes vectorielles SVG en OpenGL|ES, alors je vous suggère de faire le parseur et la logique vous-même. Notez que SVG est une énorme spécification, avec différentes fonctionnalités comme les serveurs de peinture (gradients, motifs ...), les références, les filtres, le détourage, la gestion des polices, les animations, les scripts, les liens, etc, etc.

Si vous voulez un support complet des svg, il existe une bibliothèque sur http://code.google.com/p/enesim appelé egueb (et particulièrement esvg) qui utilise enesim (une bibliothèque de rendu qui a des backends software et opengl) 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, ce qui vous permet de vous adapter à vos besoins particuliers, comme modifier la scène rendue, la transformer, etc. Parce que le dessin en gl est toujours fait dans une texture.

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

La deuxième option consiste à utiliser des bibliothèques qui effectuent un rendu sur une texture. Bien que cela puisse convenir pour graphiques vectoriels statiques, ce n'est pas une option efficace ou faisable pour les jeux où la mise à l'échelle et les rotations sont fréquentes.

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

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

7voto

ClayMontgomery Points 1584

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

SVG et OpenVG ont été créés par des développeurs qui comprenaient mal le fonctionnement des moteurs graphiques 3D modernes (listes de triangles). Ils ont été créés pour être une alternative ouverte à Adobe Flash, qui possède également la même architecture défectueuse qui a fait que Flash est vilipendé dans l'industrie pour ses 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 sera mille fois plus performante et vous pourrez plus facilement déboguer votre code que celui de quelqu'un d'autre.

3voto

Calvin1602 Points 5922

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 bien un VBO. Je vous suggère donc de créer votre propre analyseur SVG ou d'utiliser un analyseur préétabli, et de transférer les appels à 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 je lis correctement le code). Donc même si vous le compilez en utilisant le 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... j'espère pour le mieux). L'autre option, bien sûr, est de porter le code de C à Java. Peut-être pas aussi douloureux que vous pouvez l'imaginer.

Bonne chance !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X