Master 2 IICI - Projet 150 heures – année 2007/08 Affichage et rendu 3D pour un environnement Java d'analyse d'image Encadrant : Sébastien Lefèvre Etudiants : Matthieu Dirrenberger / Vincent Colas Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java 1 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Sommaire Introduction............................................................................................................................................. 3 Les Choix technologiques ........................................................................................................................ 4 OpenGL 2.0 .......................................................................................................................................... 4 Shaders GLSL ....................................................................................................................................... 5 Java 3d ................................................................................................................................................. 6 JOGL ..................................................................................................................................................... 6 Mise en place de JOGL............................................................................................................................. 8 Installation ........................................................................................................................................... 8 Configuration de la machine virtuelle Java ......................................................................................... 8 Matériel graphique requis : ................................................................................................................. 8 Algorithme de rendu 3d topographique ................................................................................................. 9 Algorithme ........................................................................................................................................... 9 Algorithme de rendu volumique : ......................................................................................................... 11 Comment afficher 134 000 000 de cubes ?....................................................................................... 11 Comment passer de 1Go à 10 Mo de données et l’animer de façon fluide ? ................................... 12 Algorithme : ....................................................................................................................................... 13 Exemples : ......................................................................................................................................... 14 Traitements d’image 2d accélérés par Shaders : .................................................................................. 16 Les filtrages :...................................................................................................................................... 16 Le FrameBuffer : ................................................................................................................................ 18 Algorithmes divers :........................................................................................................................... 18 Conclusion : ........................................................................................................................................... 19 2 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Introduction Le sujet que nous avons choisi de traiter consiste à pouvoir visualiser en 3d des données n’étant pas initialement prévues pour un rendu 3d. En effet, les coupes 2d d’un scanner ne sont pas aisément visualisables, car elles nous donnent des données volumiques et non pas surfaciques, ce qui pose quelques problèmes tels que la taille des données à traiter ou des soucis de qualité d’affichage. Le travaille réalisé s’articule autours du la librairie Pelican qui est une plate forme de développement et d’outils liés à l’imagerie 2d. Cette plate forme est développée en Java permettant ainsi une grande compatibilité et une redistribution on-line plus facile. Nous verrons par la suite les choix techniques que nous avons faits pour pouvoir intégrer nos outils de visualisation 3d à Pelican, puis nous présenterons une méthode de rendu 3d topographique pour images 2d en niveaux de gris, ainsi qu’une méthode de rendu 3d volumique de coupes en niveaux de gris. Enfin nous présenterons quelques techniques de traitement d’image 2d développées grâce aux shaders qui permettent un traitement très rapide des images, notamment une technique basée sur le « frame buffer » qui permettra d’affiner le rendu 3d en temps réel. 3 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Les Choix technologiques OpenGL 2.0 Dans un souci de compatibilité inter-systèmes il paraît évident d’utiliser OpenGL pour gérer l’affichage 3d. OpenGL est une interface permettant de communiquer directement avec la carte graphique en lui envoyant des primitives 3d telles que des coordonnées de sommets 3d à afficher. Le seul concurrent sérieux d’OpenGL 2.0 est Microsoft DirectX 10, mais cela nous contraindrait à utiliser uniquement Windows pour nos Viewers 3d car l’interfaçage DirectX/Java n’est que supporté sous Windows dans Java3d. De plus cette version est incomplète par rapport à la version OpenGL de Java 3d. Quand nous parlons d’OpenGL, nous précisons OpenGL 2.0 car nous utiliserons par la suite les shaders GLSL (OpenGL Shaders Language) de la carte graphique, qui sont de petites unités de calcul parallèles très utiles et puissantes. Il est à noter qu’OpenGL jusqu’à sa version 1.4 ne supporte pas la programmation des shaders, et qu’ils ne sont disponibles qu’à partir de la version 2.0. Pour pouvoir utiliser OpenGL en Java nous avons besoin de Binding Java/OpenGL. La plupart des implémentations OpenGL sont écrites en C. Donc nous ne pouvons pas y accéder tel quel. On utilisera JNI (Java Native Interface) qui permet d'utiliser du code natif écrit en C/C++ dans du Java. Ceci permet de mettre en œuvre l'idée du binding OpenGL à travers JOGL. Il s'agit d'une API utilisant JNI pour accéder à l'implémentation en C d'OpenGL. Donc toute cette gestion d'accès au code natif est faite à l'intérieur de cette API. Au final, nous avons des API permettant d'utiliser l'OpenGL (presque) comme si l'on développait en C. Pour ce qui est des performances, elles sont quasiment identiques à celles du C (en ajoutant les appels JNI et diverses petites choses). Il est nécessaire d’éclaircir quelques peu le fonctionnement des shaders GLSL car nous en parlerons tout au long du rapport. http://www.opengl.org/ 4 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Shaders GLSL L’utilisation des shaders GLSL est primordiale, c’est là que réside tout l’intérêt d’OpenGL 2.0 en permettant d’accélérer les calculs par le biais des unités de calcul vectorielles. Ces deux vues du pipeline graphique permettent de voir la différence entre les « vertex programs » gérants la géométrie c'est-à-dire les coordonnées des sommets dans R3, et les « fragments programs » gérants le remplissage des polygones dessinés en appliquant une interpolation des couleurs entre les différents sommets (une couleur est définie pour chaque sommet). Il est avant tout important de comprendre que ces unités de calcul vectorielles sont nombreuses et travaillent en parallèle pour accomplir ces tâches. Bien qu’étend initialement prévues pour gérer des questions d’affichage 3d, nous allons montrer par la suite comment détourner leur utilisation en vue de faire du traitement d’image 2d, et du rendu 3d topographique et volumique. http://www.opengl.org/documentation/glsl/ 5 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Java 3d Bien que nous utilisions JOGL, il paraît important de citer Java 3d qui aurait pu être utilisé. En effet, Java 3d est une API interagissant avec OpenGL 1.4. Comme nous l’avons précisé précédemment OpenGL 1.4 ne permet pas l’accès aux shaders, ce qui nous aurait pénalisés sachant que nous les avons utilisés dans tous les algorithmes. Il faut cependant bien voir que si nous n’avons pas choisi Java 3d, ce n’est pas pour son incapacité à gérer les shaders mais bien parce qu’il est trop lent pour le volume de données que l’on a à traiter en rendu volumique. Bien qu’OpenGL fonctionne directement avec le driver de la carte graphique, il est ici appelé par la machine virtuelle après interprétation du code objet Java ce qui entraine une certaine perte de performances. Il faut également préciser que le langage de l’API Java 3d est très différente syntaxiquement à OpenGL ce qui ne facilitera pas la maintenance du code par une tierce personne. Au contraire JOGL reprenant exactement OpenGL, il sera facile pour une personne connaissant OpenGL de reprendre le code. Par ailleurs, Java 3d requiert également l’installation de dll ou de so dans son répertoire pour pouvoir communiquer avec OpenGL. Java3D est développé par Sun mais est devenu libre. Il n'évolue plus énormément pour privilégier JOGL, mais depuis peu il a retrouvé un certain engouement auprès des développeurs. Le projet LG3D de Sun (VM en 3D) l'utilise. Il est construit directement au dessus d'OpenGL et de Direct3D pour Windows (même si cette dernière API va être abandonnée par Java3D). Il est encore pas mal utilisé mais pas pour les jeux et autres applications où les performances sont primordiales. Cependant son architecture est très bonne car il s'agit d’un modèle hiérarchique représentant le monde 3D, orienté objet, sous forme d'un arbre acyclique. JOGL JOGL est la clé de voute du projet, c’est ce qui nous permet de réellement faire de la 3d. En effet nous disions précédemment que Java 3d avait quelques problèmes de vitesse d’exécution et qu’il n’intégrait pas la programmation des shaders ne gérant pas OpenGL 2.0 mais seulement OpenGL 1.4. JOGL permet de régler ce problème car il fait le lien direct entre les commandes OpenGL dans le code Java et le driver OpenGL 2.0 ce qui nous permet d’obtenir une vitesse d’exécution proche du C et surtout cela nous permet de profiter pleinement d’OpenGL dans sa dernière version en passant outre les problèmes d’interfaçage/surcouche logiciel de Java 3d. L’API JOGL est développée par Sun et Silicon Graphics, elle est libre et est sous Licence BSD. C'est l'API de référence pour faire de l'OpenGL en Java. JOGL est une API dans un style OO (Object Oriented), c'est à dire que l'API est orienté objet, alors que l'implémentation en C ne l'est pas. Un des points intéressants est le fait que le JSR-231 (évolution actuelle de JOGL) va remplacer l'ancien JOGL et sera certainement incorporé directement dans le futur JDK. En effet pour le moment JOGL nécessite l’utilisation de quelques dll ou .so pour fonctionner, et même si elles ne sont pas lourdes (moins de 300 Ko) il faut encore les intégrer dans le répertoire où se trouve le Jar et indiquer le bon ClassPath lors de l’exécution. Une fois le JSR-231 intégré au JDK, ces librairies dynamiques ne seront plus nécessaires. 6 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Un autre point intéressant est à prendre en compte. Si la librairie est intégrée au projet il deviendra également possible de l’utiliser pour les applications 2d du projet Pelican. L’implémentation de Java 2d dans la version 6.0 du JDK (Mustang) permet une interopérabilité parfaite et puissante avec JOGL. Il suffira d’utiliser des GLJPanel widget pour obtenir une intégration Swing à 100% accélérée de façon Hardware par OpenGL. Ces accélérations peuvent notamment servir à améliorer la qualité de la fluidité lors de lectures vidéo et non pas juste pour l’affichage 3d. Des explications sont données à l’adresse suivante : https://jogl.dev.java.net/BOF-3908-JOGL-slides.pdf Nous comprenons bien que le fait que c’est une réelle difficulté d’inclure des librairies sous forme de dll ou so au projet, mais il faut voir qu’il sera impossible de traiter le problème du rendu volumique sans utiliser OpenGL de façon directe. Pour donner un exemple en terme de performance, le rendu avec utilisation de shaders n’est que moyennement fluide lorsque l’on tourne un objet codé en niveau de gris sur 512*512*81 voxels, avec un PC équipé d’un processeur Intel E6600 Core2duo, de 2 Go de mémoire à 800MHz et d’une carte graphique GeForce 8800 GTS 640 Mo. On peut donc voir ici que le problème de lenteur est déjà présent sans une gestion CPU de l’affichage mais uniquement à cause des calculs intermédiaires effectués par Java qui ralentissent l’affichage. C’est pour ça qu’il faut déporter un maximum les calculs vers le GPU. Nous avons fait une version CPU de l’algorithme de rendu topographique qui fonctionne sans shaders, mais cela n’enlève pas la contrainte d’avoir accès à OpenGL pour l’affichage… Nous expliquerons également comment le faire pour le rendu volumique. Cependant cela demanderait beaucoup de prétraitements, mais nous y reviendront en détails dans la partie traitant du rendu volumique. Pour résumer les avantages et les inconvénients des deux technologies existantes pour afficher de la 3d en Java : - Java 3d est plus lent mais plus objet, c'est-à-dire plus « Java » JOGL est très similaire à OpenGL et donc très rapide avec une accélération matérielle égale à ce que permet un programme codé en C. La seule limitation en performance viendra des temps de traitements de données par Java. 7 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Mise en place de JOGL Installation Pour faire fonctionner nos algorithmes dans Pelican, il faut installer la librairie JOGL et configurer le CLASSPATH du système lors de l’exécution pour pouvoir accéder à la librairie. L’installation de la librairie se résume à créer un répertoire contenant les fichiers suivants : jogl.jar jogl.dll / jogl.so gluegen-rt.jar gluegen-rt.dll / gluegen-rt.so jogl_awt.dll / jogl_awt.so Configuration de la machine virtuelle Java On commence par configurer la machine virtuelle java pour avoir suffisamment de mémoire vive en RAM allouée. On défini 1 Go de mémoire mémoire RAM allouée : -Xmx1G On désactive l’affichage standard pour Java 2d de manière à ce qu’il ne cause pas de conflits sous windows et on active OpenGL (optionnel) : -Dsun.java2d.noddraw=true -Dsun.java2d.opengl=true On utilisera la commande suivante pour configurer le CLASSPATH et lui indiquer où trouver la librairie: -Djava.library.path=C:\DIRECTORY –classpath Dans le cadre de notre projet il sera plus simple d’intégrer les Jar dans le répertoire des librairies de Pelican ainsi que les dll ou so correspondants. Matériel graphique requis : Cartes graphiques minimales supportant les shaders OpenGL 2.0 (fragments+vertex shaders): - nVidia GeForce 256 ATI Radeon 7500 S3 Savage 3D 8 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Algorithme de rendu 3d topographique L’algorithme de rendu 3d topographique est basé sur une technique classique utilisée en imagerie. Nous l’avons adaptée de manière à utiliser les shaders pour le calcul de la hauteur, ce qui apporte un gain de rapidité. Le conceptt de base consiste à définir un pseudo cube dans lequel sera dessiné l’image 2d en niveau de gris. Les axes X et Y restent similaires à ceux de l’image 2d originale. Seul l’axe Z varie en fonction de l’intensité du niveau de gris de chaque pixel. Il en résulte résulte une image dans laquelle les pixels sombres sont plus bas et les pixels clairs sont plus hauts. Ce type d’image s’appel « carte de hauteurs » d’une image. Ce procédé est couramment utilisé en imagerie 3d pour stocker et afficher le relief d’un paysage à grande échelle, cependant cela pose quelques limites. On ne peut pas avoir deux hauteurs différentes au même endroit, donc les grottes et falaises abruptes sont impossibles à représenter avec ce modèle. Ceci dit, il a l’avantage d’être léger et rapide à calculer. Algorithme L’algorithme utilise des GL_QUAD reliés entre eux. Chaque pixel correspond à un GL_QUAD et chacun de ces GL_QUAD se situe à la hauteur normalisée correspondant à l’intensité du pixel concerné. Un GL_QUAD est unee primitive OpenGL composée de quatre sommets dans R3, c'est-àc'est dire un carré positionné dans un espace 3d. Chacun des GL_QUAD a une taille correspondant aux dimensions de visualisations divisées par le nombre de pixels à voir. Ainsi un shader détermine la position en X, Y en fonction des coordonnées du pixel en cours de traitement. La position en Z du GL_QUAD est déterminée par l’intensité du pixel. 9 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Exemple de code du shader concerné : uniform float pasZ; varying vec4 colors; void main() { //gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex; vec4 postmp=gl_Vertex; colors=gl_Color; float color=colors.r+colors.g+colors.b; float tmp=(color/3.0); vec4 pos=vec4(postmp.x,tmp,postmp.z,postmp.a); gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * pos; } Pour plus d’informations concernant le fonctionnement des shaders GLSL rendez-vous sur la page suivante : http://www.opengl.org/documentation/glsl/ Il faut préciser que chacune des unités de calcul vectoriel de la carte graphique calcule en parallèle un autre pixel. Sachant que dans une carte récente on trouve jusqu’à 128 unités de calcul, on peut facilement imaginer le gain en temps de calcul par rapport à un calcul entièrement supporté par le processeur central de la machine… Voici un exemple de rendu topographique à l’aide notre viewer 3d topographique qui permet de manipuler l’image grâce à un trackball virtuel : 10 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Algorithme de rendu volumique : L’algorithme de rendu volumique nous est de loin la chose qui nous a le plus intéressé dans ce projet. La mise au point de cet algorithme nous ai pris beaucoup de temps, car il est délicat d’afficher un grand nombre de voxels à l’écran. Comment afficher 134 000 000 de cubes ? Une première approche naïve que nous avons testée est d’afficher simplement chaque voxel sous la forme d’un cube, sachant qu’un voxel s’apparente à un cube … Pour donner un exemple concret, il suffit d’imaginer un petit cube de voxels de 512*512*512, ce qui donne 134 217 728 voxels à afficher. Si l’on converti ce nombre en cubes, cela revient à afficher: 134 217 728 voxels * 6 faces * 2 triangles par faces soit 1 610 612 736 triangles. On ajoute à ce nombre de triangles : 1 610 612 736 triangles * 3 sommets * 4 octets pour stocker en mémoire les indices des sommets ce qui donne 18 Go de données simplement pour stocker les indices des sommets des triangles de nos faces… Pour la liste des sommets on a 134 217 728 voxels * 8 sommets * 3 coordonnées * 4 octets (float) soit 12 Go de données. On précise bien sûr qu’on se situe dans le cadre d’un modèle binaire et qu’il ne faut pas 4 octets pour stocker un niveau de gris… Ces nombres éloquents démontrent clairement que même avec une bande passante de 1 To et des capacités de plus en plus importantes, les cartes graphiques et les machines d’aujourd’hui arrivent difficilement à calculer un tel affichage. Il faut préciser que ce calcul n’est vraiment pas optimisé sachant que l’on peut assez facilement réduire le nombre de sommets en les partageant, de même pour les faces. Cela nous amènerait tout de même à une charge mémoire de l’ordre du Giga octet ce qui reste impossible à afficher tel quel. Bien sûr nous parlons ici d’un affichage pré-calculé et géré par le CPU, l’affichage des données étant lui seul attribué à la carte graphique. Nous avons tout de même testé cette solution pour vérifier rapidement que nos données étaient bien chargées en mémoire. Il a fallu élargir quelques peu la capacité mémoire de la machine virtuelle en mettant 1Go. Nous avons décidé d’utiliser une technique de sous-échantillonnage, car nos machines n’arrivaient pas à afficher le modèle de base. Le sous-échantillonnage a été testé à trois niveaux 1/8, 1/64 et 1/512. Sous-échantillonner à 1/8 ne change pas beaucoup le problème d’affichage. La machine arrive à afficher à raison d’une image toutes les 15 secondes. Le sous-échantillonnage à 1/512 est quand à lui un peut trop drastique… Enfin le sous-échantillonnage à 1/64 a donné des résultats visuellement convenables, cependant, l’affichage reste trop lent avec une image toutes les 3 secondes… 11 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Comment passer de 1Go à 10 Mo de données et l’animer de façon fluide ? On peut se demander comment gérer cet affichage car même si nous trouvons d’autres polygones simplifiés permettant d’afficher le résultat de chaque voxel, il restera quand même 134 217 728 éléments à afficher. Nous avons du réfléchir autrement. Si on part de la structure de données initiale, on obtient des coupes 2d empilées les unes sûr les autres. Ces coupes 2d peuvent être vues comme des textures empilées ou plus simplement une texture 3d. A partir de là, on sait que nos shaders peuvent faire des calculs et interagir lors du remplissage de la couleur d’une texture. L’idée finalement très simple est de charger chaque plan 2d du modèle de départ dans une texture 3d OpenGL. Cette texture pourra par la suite être traitée par le shader qui calculera le niveau de transparence de chaque pixel et sa couleur. Toute la difficulté étant maintenant de trouver un système d’affichage ne présentant pas d’artefacts trop flagrants. En effet, à partir du moment où l’on affiche des textures sur des plans, un certain nombre de problèmes apparaissent. Lorsqu’on affiche des plans parallèles les uns aux autres et que la profondeur en Z est simplement donnée par l’espacement des plans il y a des zones vides qui sont visibles si l’on place une camera sur le côté. Pour palier à ce problème nous avons créé un system qui fabrique des textures pour chaque angle de vue. Ainsi les textures correspondantes à l’angle de vue courant sont affichées. Cela peut créer un léger effet de « popping » si l’on déplace d’avant en arrière l’objet à une zone frontière, mais la résolution étant généralement assez élevée, cela n’est pas vraiment problématique. 12 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Dans les différents exemples qui suivront, c’est la carte graphique qui par le biais de ses unités de calcul évalue pour chaque « pixel » son opacité et sa couleur, ce qui déporte un maximum les calculs et laisse le CPU tranquille. Il est cependant possible de faire tout ces calculs sur le CPU en précalculant les pixels de chacune des 6 séries de textures possibles. Ce prétraitement prendrait beaucoup de temps (plusieurs secondes) mais permettrait d’afficher simplement ces textures précalculées à l’aide d’OpenGL 1.4. L’intérêt serait simplement de pouvoir faire fonctionner l’algorithme sur un ordinateur équipé d’une vieille carte graphique ne gérant pas les shaders 2.0 (cartes graphiques avant 2003). Algorithme : 13 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Exemples : Voici quelques exemples de résultats obtenus sur l’objet dont nous disposions. Il faut préciser que cet objet a une résolution de 512*512*81 voxels ce qui représente tout de même 21 233 664 voxels, ceci dit, l’objet s’anime de façon fluide lorsqu’on le fait pivoter à l’aide de la souris. On peut voir sur ces exemples différents réglages de couleurs ou de transparences selon les composantes (intervalles d’intensités) choisies. Grace à ces réglages, on peut facilement faire ressortir la composante désirée. 14 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Voici deux exemples en vues multiples : 15 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Traitements d’image 2d accélérés par Shaders : Lors de nos expérimentations durant la mise au point des algorithmes de rendu topographique et volumique, nous avons utilisé des shaders. Maîtrisant bien l’utilisation de ces unités de calcul performantes, nous nous sommes dit qu’il serait intéressant d’intégrer des traitements d’image 2d classique dans Pelican grâce aux shaders. Le schéma suivant illustre la façon la plus simple d’effectuer un traitement d’image 2d en la chargeant sous la forme d’une texture appliquée sur un quad OpenGL que l’on envoie à la carte graphique : Les filtrages : Les algorithmes de filtrages sont conçu d’une manière qui les rends très facilement parallelisables ce qui nous a permis d’assez facilement intégrer les fonctions de filtrage classiques à Pelican sous forme de shaders. 16 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Voici le code d’un filtrage gaussien sous forme d’un fragment shader GLSL : #define KERNEL_SIZE 9 const float kernel[KERNEL_SIZE] = 1.0/16.0, 2.0/16.0, 1.0/16.0, }; { 2.0/16.0, 1.0/16.0, 4.0/16.0, 2.0/16.0, 2.0/16.0, 1.0/16.0 uniform sampler2D colorMap; uniform float width; uniform float height; const float step_w = 1.0/width; const float step_h = 1.0/height; const vec2 offset[KERNEL_SIZE] = { vec2(-step_w, -step_h), vec2(0.0, -step_h), vec2(step_w, -step_h), vec2(-step_w, 0.0), vec2(0.0, 0.0), vec2(step_w, 0.0), vec2(-step_w, step_h), vec2(0.0, step_h), vec2(step_w, step_h) }; void main(void) { int i = 0; vec4 sum = vec4(0.0); vec4 tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[0]); sum += tmp * kernel[0]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[1]); sum += tmp * kernel[1]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[2]); sum += tmp * kernel[2]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[3]); sum += tmp * kernel[3]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[4]); sum += tmp * kernel[4]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[5]); sum += tmp * kernel[5]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[6]); sum += tmp * kernel[6]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[7]); sum += tmp * kernel[7]; tmp = texture2D(colorMap, gl_TexCoord[0].st + offset[8]); sum += tmp * kernel[8]; gl_FragColor = sum; } Cet exemple nous montre très clairement qu’il est facile d’utiliser des unités de calcul vectorielles pour ce type d’opérations. 17 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Le FrameBuffer : Le FrameBuffer est le buffer d’affichage d’OpenGL et il est intéressant de pouvoir faire des traitements 2d dessus pour le rendu final. Si on applique un filtrage 2d sur le FrameBuffer qui est similaire à une image ou une texture, on peut filtrer le rendu d’une scène 3d. Comme par exemple faire un filtrage à l’aide d’une gaussien sur notre rendu volumique pour lisser les imperfections graphique en temps réel. Le point fort est le filtrage/traitement temps réel qui s’effectue sur une fenêtre de taille conséquente en temps réel grâce aux shaders. Exemple avec lissage Gaussien temps-réel sur la scène de rendu volumique: Cette technique est d’ailleurs utilisée dans la plupart des jeux pour lisser le rendu sans consommer trop de ressources. La fonctionnalité n’est pas encore tout à fait implémentée par manque de temps, mais elle le sera probablement rapidement. Algorithmes divers : Il sera tout à fait possible d’adapter d’autres algorithmes plus complexes aux shaders, c’est d’ailleurs dans cette optique que nous avons testé les applications 2d avec shaders. Les filtrages et le FrameBuffer sont les plus faciles à implémenter et par manque de temps, nous avons préféré faire fonctionner ces algorithmes simples plutôt que de perdre trop de temps sur un algorithme plus complexe qui n’aurait peut être pas fonctionné au final. 18 Rapport de projet 150h – M2 IICI – Affichage et rendu 3d pour un environnement Java Sachant que le traitement 2d par shader n’était pas un élément du sujet nous n’avons pas passé trop de temps dessus, cependant nos recherches ont permis d’aboutir à la conclusion suivante : Quand Pelican intégrera JOGL, il sera possible de repasser un grand nombre d’algorithmes de traitements 2d sur shaders et du coup rendra la plate forme beaucoup plus performante. Certes le calcul vectoriel ne permet pas tout, mais les dernières évolutions en termes de pipeline des cartes graphique permettent des traitements plus évolués avec des boucles et des accès en écriture dans les textures. Il n’y a donc quasiment plus de limite concernant les algorithmes. Evidemment certains algorithmes très linéaires et itératifs n’ont aucun intérêt à être codés de cette façon, mais tous les autres ont tout intérêt à l’être. Conclusion : mlkmlk 19