InExtremis

Projet de programmation. Librairie 3D - TEMPS REEL - utilisant OpenGL et GLSL écrite avec le langage C++. Cette librairie représente mes études dans le domaine de la 3D temps réel et n'a pas d'autres ambitions pour l'instant. Ce travail est réalisé comme travail de fin d'études pour le département d'algorithmique de l'Université de Liège.

18.10.08

Exploitons le deferred lighting

Un grand classique, quand on fait du deferred lighting, c'est de montrer que son modèle d'éclairage est 100% dynamique. On attache donc une source lumineuse aux particules d'un système de particules et le tour est joué. C'est donc ce que j'ai rapidement fait avec mon nouveau module de détection de collisions.



Dans cet exemple, on peut remarquer que le système de collision est montré dans un niveau à géométrie arbitraire, histoire de se convaincre que cela n'est pas limité à une petite pièce rectangulaire!

>>> fichier xvid <<<

Détection de collisions

J'ai ajouté un module de détection de collisions. Le but étant d'éviter que notre camera virtuelle ne se promène à travers les murs. Conceptuellement parlant, il est possible de "questionner" le niveau actuellement chargé (la scène) en demandant si, pour un rayon dans l'espace donné, une intersection est détectée.

Cela a immédiatement amené à un petit enrichissement des propriétés des objets pour qu'ils soient gérables par un petit module physique très simple... pour l'instant.


(Dans cette vidéo, on peut observer des artefacts dus aux ombres portées... ça c'est une autre histoire !)

>>> fichier xvid <<<

17.9.08

D3 Maps & Procs

Dernièrement, j'ai travaillé sur un module d'import 100% automatique des cartes de Doom3 (aka idtech4). Cela n'est pas si facile que je l'avais pensé, mais ça avance.

Voici un premier jet sous forme d'une soupe de triangles éclairée.


L'étape suivante a été d'affecter des matériaux à cette soupe. C'est là que les choses sont devenues un peu plus difficiles. La difficulté vient de la gestion des milliers de matériaux utilisés dans un seul niveau. Ces matériaux sont définis dans des fichiers de scripts, dont je n'ai que faire (et surtout dont j'ai déjà une version maison). J'ai donc programmé un convertisseur de définitions de matériaux. Cela marche à 80% pour l'instant (j'ai des problèmes avec les matériaux transparents, sans grande surprise, puisque j'ai totalement mis cet aspect de mes matériaux de côté depuis un moment...)

Voilà ce que ça donne :





Il faut noter que le nombre d'images calculées par secondes a chuté (c'est un bel euphémisme). Mais c'est parfaitement normal, puisque je n'ai pas encore adapté mon système de calcul de visibilité. Cela rentrera dans l'ordre un jour ou l'autre, suivant le temps dont je dispose pour faire avancer ce projet.

22.7.08

Je ne l'ai jamais signalé ici, mais je maintiens (un peu) une page sur un autre site internet qui parle de ce projet.

On peut y voir des vidéos.

Pour ceux que ça intéresse :
http://www.degbomont.net/ie/ie.html

4.7.08

Que la lumière soit (en retard) !

Je joue avec différentes approches pour gérer la lumière dans une scène complète.
En effet, alors qu'une scène de "démo" typique ne contient que quelques objets et une ou deux sources lumineuses, une scène tentant de représenter un monde est volumineuse et, surtout, présente des centaines des sources lumineuses.

Quand un triangle est dessiné, les cartes graphiques limitent le nombre de lumière l'influençant à 8. Cela rejette déjà la possibilité de simplement stocker en mémoire graphique l'ensemble des lumières et dessiner le monde en en tenant compte.

Ensuite, quand un objet composé de milliers de triangles est dessiné à l'écran, on veut à tout prix éviter de devoir modifier l'état de la carte graphique pour chaque triangle. on désire encore plus éviter de faire transiter des informations sur le bus pour chaque triangle. Impossible donc d'envoyer un triangle à la fois avec ses lumières...

Il faut donc organiser notre scène. Le problème est qu'alors que l'on peut définir un sous ensemble de lumières affectant un objet, on ne peut pas nécessairement en fixer le nombre.

Une solution classique consiste donc à dessiner N fois le triangle (si il est éclairé par N lumières) et combiner les images produites pour afficher le résultat final.

C'est cette technique qui est employée par DOOM 3 (idtech 4). Le problème c'est qu'avec cette technique, on doit passer la scène en revue plusieurs fois pour la dessiner.

95% des jeux vidéos, autres que doom3, utilisent ce que l'on appelle des "lightmaps". C'est à dire que le décor n'est pas affecté par la lumière, mais nos le fait croire en précalculant les intensités lumineuses de chaque triangle du monde. Ils n'utilisent réellement les lumières que pour dessiner les objets dynamiques tels que les acteurs.

Uen technique assez peu répandue, mais qui semble intéressante est le deffered shading (je n'en suis pas l'inventeur !). Cela consiste en la production de plusieurs images, contenant des informations nécessaires aux calculs des éclairages.

La scène est donc parcourue une seule fois et ces images sont produites (typiquement 4).

Une fois ces images générées, appliquer une lumière sur la prise de vue ne nécessite que le dessin d'un rectangle en 2D sur l'image résultante. tous les pixels de ce rectangle vont lire les 4 images produites, pour calculer l'éclairage qu'ils devraient avoir reçus si la lumière avait été présente dans la phase de dessin de la scène. Cela permet d'avoir énormément de sources lumineuses tout en conservant un parcours unique sur la scène.

Cela semble bien en théorie mais il faut une carte graphique très costaude pour générer les images initiales.



J'ai écrit un module de rendu que j'ai ajouté à IE pour gérer cette technique. Les résultats sont assez satisfaisants, bien que tout de même lents. Mais il faut bien se rendre compte que TOUTES les lumières sont 100% dynamiques, elles peuvent changer de forme, de couleur, de position, de nature... etc. Ce que l'on ne voit JAMAIS dans des applications temps réel.

8.11.07

ScreenSpace Soft Shadows

J'ai implémenté une technique très simple d'ombres douces, il s'agit de calculer une image qui représente les zones dans l'ombre depuis la caméra. Cette image est ensuite filtrée avec un filtre de flou gaussien (x puis y) et l'information résultante est utilisée dans le rendu final pour donner des ombres à contours doux.

Cette méthode est très simple mais :
- elle est physiquement totalement farfelue
- des artefacts arrivent aux silhouettes des objets



J'ai cependant amélioré le traitement, et je n'applique plus un simple flou gaussien, ce qui me débarasse de quasiment tous les artefacts visuels. Je trouve les résultats satisfaisants, surtout que le cout du calcul d'ombres douces devient totalement indépendant du nombre d'objets présents ainsi que du nombre de sources lumineuses.

3.11.07

Shadow Mapping

Beaucoup de travail sur le rendu des ombres... Beaucoup de résultats différents. Je confirme ce que tout le monde dit : les shadow maps, c'est bien ; mais la robustesse relève réellement de peaufinage. On se retrouve très rapidement à régler des micro-détails qui peuvent conduire à des incohérences de rendu.

10.10.07

Shadow Maps

Une autre technique de calcul d'ombre à été implémentée dans le moteur, il s'agit de la technique des shadow maps. Tout le monde semple dire qu'elle est plus simple à mettre en oeuvre que les stencil shadows, je ne partage pas cet avis. Bien les utiliser représente un certain défi. Disons qu'il est peut-être plus facile de l'intégrer dans une architecture existante. Enfin, IE propse désormais cette fonctionnalité également. Il reste maintenant à en adoucir les contours.

CPU Skinning

Il est désormais possible d'animer les modèles 3D affichés dans le moteur. L'animation se base totalement sur le système vu dans DOOM 3. Je l'ai cependant intégralement écrit sur base de l'observation de leur système. Il est également possible d'afficher les "squelettes" d'animations.

Le principe d'animation est assez simple, une fois assimilé (comme souvent !). En fait un vertex (poin dans l'espace) de la surface d'un objet animé dépend de la position des points clés (les articulations en quelque sorte). Sa position peut dépendre de plusieurs articulations. Une animation est une succession de positions d'articulations capturées à des instants clés dans le temps à intervals réguliers. La position entre ces trames est interpolée sphériquement (SLERP+Quaternions).

Principe maintenant bien connu, mais intéressant à implémenter :)

Depth of Field (basic version)



IE gère à présent les paramètres propres à la caméra utilisée pour visionner la scène. Il est donc possible de définir la focale de la caméra pour obtenir un effet de flou focal. Dans cet image, l'effet est exagéré pour mettre l'effet en évidence.

Eau ++

L'effet permettant de gérer les surfaces d'eau a été revu pour permettre d'en modifier les paramètres dynamiquement.

Cela permet de donner des aspects totalement différents selon les situations et les effets désirés. En effet, de l'eau n'aura pas le même aspect si elle est dans une mare ou dans un verre...

Voici trois jeux de paramètres différents :


Paramètres d'un verre d'eau, par exemple.



Paramètres d'un lac.



Surface de l'océan...

Glow

Les objets possèdent un paramètre supplémentaire qui permet de définir des zones auto-éclairantes à leur surface. Même en l'absence de toute lumière, ces zones sont visibles. Bien qu'étant extrèmement simple à intégrer, cela ajoute une pointe de réalisme.

25.9.06

Pipeline



Juste une image pour montrer l'évolution du projet...

20.9.06

Ombres++



IE s'est vu offrir un nouveau pipeline graphique, totalement réécrit.
Ce nouveau pipeline permet des combinaisons beaucoup plus riches de tout ce qui avait déjà été programmé. Le rendu s'en trouve beaucoup amélioré.



Côté optimisations, l'extrusion de la silouhette en GPU pose encore des soucis, et donc, le frame rate a pas mal baissé... J'espère trouver une solution rapidement.

12.8.06

Ombres



IE possède un mécanisme de projection d'ombres. Cela amène beaucoup de réalisme aux scènes visionnées. Ces ombres sont pour l'instant limitées à une seule lumière. Les résultats sont assez convainquants. La technique utilisé est le stencil shadow volume... pas évident à maitriser, mais assez robuste.

22.7.06

Moins intéressant


Il est possible de changer dynamiquement les modes d'affichages des objets pendant l'exécution du programme, pour visualiser certaines informations. Ici je montre le mode de Debug.

Bien sur ces modes ne sont pas tous destinés à réaliser des visualisation techniques.

Reflets dynamiques



Les reflets dynamiques ont été améliorés, ils sont visuellement beaucoup plus convainquants. En fait, les reflets sont devenus très paramétrables et permettent de ne réfléchir, par exemple que les sources importantes de lumière de l'environnement (ce qui peut inclue des objets fortement réfléchissants!). Cela permet de se passer des calculs de reflets spéculaires de phong dans l'éclairement des objets. On ajoute de la complexité de calcul pour en retirer d'autre part, mais en améliorant la qualité visuelle. Un technique intéressante.

Les reflets spéculaires ne dépendent donc plus des sources lumineuses, mais de l'environnement qui entoure les objets, que cet environnement soit une simple texture ou une scène complexe.

14.7.06

Eau


IE intègre à présent un nouveau type de shader, capable de générer une surface présentant des refractions et des réflexions. Ici c'est une scène comportant un lac qui est montrée, à titre d'exemple. On remarque que c'est un bon début, cependant, je dois encore me débarasser de certains artefacts gênants sur les bords...

29.5.06

Améliorations

Les reflets dynamiques ont étés améliorés, et des combinaisons de reflets sont envisageables. On peut ainsi observer un objet réfléchissant à travers le reflet d'un autre. Les résulstats dépassent mes espérances je dois bien l'avouer.



Le bloom à encore été amélioré (question de gôuts), et il est possible de définir des environnements. Cela ajoute du réalisme aux scènes (il s'agit d'une skybox).


24.5.06

Reflets réels


IE gère à présent un nouveau type de reflet, à savoir les reflets réels. J'entends par reflets réels des reflets qui montrent la scène qui entoure l'objet dynamiquement. Si l'environnement de l'objet change, ses reflets changent également. Ce système est idéal pour les carosseries de voitures, puisque leur environnement change avec leur déplacement.

18.5.06

Adv Specular Maps


Un nouveau shader plus évolué tire parti d'un nouveau format d'image spécialement développé pour l'occasion. Ce nouveau format permet de stocker plus d'informations par unité de texture, mais bénéficie de la compression JPG.

Ce nouveau shader est destiné à permettre de faire varier les attributs (pour les connaisseurs) shininess, glossiness et specular color par pixel, via une seule unité de texture. Le résultat en image. La chose importante à constater est que les différents morceaux de l'appareil ne présentent pas du tout les mêmes types de reflets, et pourtant il s'agit d'un seul et même objet et d'une seule texture spéculaire.

5.5.06

Encore des brèves

Un effet paralax qui fonctionne bien :


Juste parce que c'est "joli" :


Variation de conditions d'éclairage d'un modèle :



27.4.06

Nouveautés

Dernières nouveautés en images

Un nouveau shader de post production (avant/après) :


Lightmaps améliorées (avant/après) :

10.4.06

Post production

Un système de shaders de post production est appliqué sur les images produites par la librairie IE. Un exemple en est le bloom. Cela permet de donner un cachet particulier à l'image. D'autres effets sont présents, mais le bloom est probablement le plus impressionant. Il est possible d'altérer les couleurs de la scène, de la rendre en noir et blanc, d'appliquer un effet de flou gaussien à l'image voire encore de déformer toute la perception de la scène comme vue à travers une lentille déformante.

20.3.06

Light Maps

IE gère les ombres d'occlusion ambiantes via Ligh Maps.
...

19.3.06

Fourrures

IE est doté de shaders spécialisés dans le rendu d'objets couverts de fourrures. C'est évidement une approximation qui fait partiellement illusion, mais c'est du temps réel, faut-il le rappeler... Le système est paramétrable et peut réaliser des fourrures via 15, 20 ou jusqu'a 30 passes. Au delà on sort d'une quelconque application en temps réel avec le matériel actuel.
J'ai ensuite utilisé ce shader en collaboration avec d'autres shaders déjà présents dans le système IE pour réaliser une scène qui présente un petit peu plus d'interrêt : dessiner des cheveux à cet horrible vieux bonhomme. Ca donne assez bien, pour un début.

9.3.06

Specular maps

Les reflets spéculaires apportent un plus pour le rendu de matières plastiques, ou métalliques. C'est un fait. Mais parfois, un seul objet, une seule entité, est composée de plusieurs types de matériaux, variant d'avantage avec la texture que l'on y applique qu'avec la géométrie réelle. Difficile donc de faire des sous-objets pour séparer les matériaux. Le problème est le plus souvent rencontré avec les reflets spéculaires. En fait, comme on peut le voir ici, appliquer les reflets sur l'ensemble du modèle discrédite très fort son réalisme, bien que ça le rende plus "spectaculaire" au niveau technique... Un absence totale de reflets discréditerait également les parties métalliques du modèle. Parfois les parties métalliques sont plus petites, ou en tout cas non confondues avec de la géométrie réelle.

C'est pour corriger ce problème, et rendre le système de matériaux plus flexible que les "Specular maps" existent dans le système IE. On a l'impression que les reflets sont supprimés, mais il n'en est rien, pour s'en convaincre, il suffit de regarder les parties métalliques comme les pieds ou l'arme sur le bras. En fait les reflets sont localisés aux bons endroits. Le fait de le voir en mouvement permet de mieux s'en rendre compte. Une "Specular Map" est une texture invisible, mais appliquée tout de même à l'objet, et suivant la couleur de la texture, on adapte le rendu du matériau présent au même endroit.

8.3.06

Matériaux transparents


IE gère les matériaux transparents, avec possibilité de déterminer un coefficient de transparence. Cette option permet assez de flexibilité pour pouvoir rendre différents type de surfaces. Cette flexibilité est encore accrue, puisque cette transparence peut être appliquée à n'importe quel matériau déjà défini via les « shaders » développés. Ici on peut voir que les fenêtres de la voiture sont transparentes, mais présentent un reflet environnemental en plus. Combiner ces éléments est l'idéal pour simuler le verre, et le "plexiglass". La transparence ici définie est cependant uniforme, c'est à dire qu'elle est appliquée à tout un objet à la fois. Ici, la vitre de la voiture, est considérée comme une entité objet différente. La technique employée est celle de la seconde passe avec objets transparents, sans mise à jour du « depth buffer », ce qui évite de devoir trier les objets de la seconde passe, propriété importante pour le rendu temps réel. Cela veut également dire que si la scène contient trop d'objets transparents se recouvrants, on peut observer des zones incorrectes ... à manipuler avec précaution donc.

25.2.06

Environnements cubiques : reflets

Pour corriger tous les problèmes des reflets précédents (spherical envmap), mon système IE gère les cubemaps. C'est en fait un ensemble de six vues prises dans les trois directions (XYZ) en positif et négatif (en avant et en arrière pour chaque axe, en quelque sorte). Ce qui revient à composer un environnement cubique. C'est beaucoup plus lourd au niveau des textures (ça en consomme quand même 6 au lieu d'une -- au niveau quantité de mémoire, pas au niveau des slots dans la vga, ça tient quand même en une seule entrée ogl) mais quelle différence au niveau de la qualité des images! Ensuite, et c'est probablement tout aussi important, c'est un relfet correct, en ce qui concerne la localisation spatiale en un point (infiniment petit). Ca n'est donc plus limité à une prise de vue, on peut se balader librement autour de l'objet réfléchissant sans observer ni erreurs, ni artefacts, ni déformations.

Ici, je montre l'effet sur le poisson, et sur le même poisson qui utilise sa texture de bump... Puisque bien sûr tout se combine aisément.

24.2.06

Reflets


Le système permet de définir des reflets statiques (entendre par là qu'ils ne sont pas le reflet d'objets de la scène, mais d'une autre scène statique, via une photographie). Le premier système géré est l'utilisation d'une image particulière qui reprend un peu plus qu'une demi-sphère de reflets, mais avec de sévères déformations comme on peut le constater. Cette image sert de référence comme source de couleur. Quand on doit déterminer quelle couleur prend un pixel d'une surface (et qu'elle est une surface réfléchissante), on calcule le vecteur reflet du vecteur de vision à la surface de l'objet (en considérant en fait la normale locale calculée en chaque point par interpolation). Cette opération a pour effet de définir un nouveau vecteur, ce vecteur est alors transformé en un second vecteur de dimension inférieuse (2D) afin de pouvoir faire correspondre chaque direction de l'espace (en fait quasi un demi-espace) avec un pixel de l'image de référence, et ce de manière cohérente.

Cette méthode fonctionne très bien, mais montre très vite ses limites. En effet, de par le fait que l'image de référence est unique et ne représente qu'un quasi demi-espace, l'espace pouvant être réfléchi est particulier à un angle de vue particulier, et les reflets ne sont donc pas satisfaisants si on se déplace. De plus (mais là c'est un problème avec mon implémentation de cette méthode) j'observe quelques artefects (défauts dans les images produites) assez embêtants.

On utilisera donc cette méthode pour générer des reflets rapidement mais à des endroits où, paradoxalement, on ne les regardera pas trop en détail.

Importeur de formats externes


J'ai réalisé un importeur de formats de données externes et je peux ainsi utiliser tout ce qui sort de 3DS MAX (ou sa précédente version gratuite GMAX), et même du jeu DOOM III. L'avantage des modèles de DOOM III est qu'ils sont parfaits pour illustrer le fonctionnement de la librairie à pleine puissance. Le gros désavantage, est que ces modèles sont absolument affreux ! Les monstres et les détails sanguinolants, ne sont pas à proprement parler présentables dans un cadre sérieux.

Juste une remarque, pour information, je ne diffuse pas de modèles de DOOM III, car ils sont protégés par les droits d'auteur. Je ne compte en faire rien d'autre que de tester mon application avec.

Textures de bump

IE gère également les texture particulières servant à faire apparaitre la géométrie de l'objet comme plus complexe. On appelle ces textures particulières des textures de bump ou Bumpmaps en anglais. A nouveau tout ici est écrit en GLSL, et le système employé pour un maximum de rapidité est le précalcul d'espace tangeant. Les résultats sont visuellement satisfaisants. La texture utilisée est en fait une height map (niveau de gris symbolisant une hauteur) transformée en normal map par précalculs.

Textures


Bien entendu le système est capable d'appliquer des textures aux modèles. Je pense que ce n'est pas très intéressant en soit de le signaler, si ce n'est qu'ici tout est géré via des shaders spécifiques en GLSL, je le rappelle. La texture peut être considérée comme une image que l'on applique telle une peau sur la surface d'un objet pour lui donner plus d'une seule couleur.

Reflets spéculaires


Les matériaux peuvent être perçus comme des matières plastiques (ce n'est pas obligatoire, le tout est hautement paramétrable) et afficher des reflets que l'on appelle reflets spéculaires. L'exemple toujours cité est celui d'une boule de billard. C'est l'exemple même du matériau qui diffuse les rayons lumineux (il a donc une couleur propre), mais qui devient réfléchissant dans une direction précise (on y voit donc la couleur de la source de lumière). Je passe les détails mais c'est géré.