cliquer - PAGE D`accueil

Transcription

cliquer - PAGE D`accueil
0.1
Il nous a paru nécessaire d'écrire une petite introduction à DirectX ainsi qu'à ses composantes
DirectDraw et Direct3D. En effet, nous allons employer de nombreux termes relatifs à ces 3 Direct. De
plus, de part la nature de notre projet, il nous à semblé indispensable de vous faire une courte
introduction sur les jeux vidéos de rôle (« RPG » : rôle playing game), qui permettra - par
comparaison - de mieux définir nos objectifs.
1. DIRECTX
DirectX est une bibliothèque de fonctions créée par Microsoft pour permettre aux développeurs
de jeux de ne plus se soucier du matériel utilisé. Ainsi un programme écrit pour un certain type de
machine doit théoriquement pouvoir marcher sur tout autre configuration (malgré le fait, par exemple,
qu'il n'y ait pas la même carte vidéo, ni la même carte son…). L'idée de départ venait du fait que dans
le monde DOS, les jeux requérant des accélérations matérielles devaient être réécrits pour chacune
des cartes du marché (carte son et 3D). Microsoft avec Windows95 eu besoin d’unifier ces
bibliothèques pour enfin pouvoir programmer des jeux en étant indépendant du matériel. Dans la
plupart des cas ceci est vérifié, même si bien des fonctions spécifiques ne sont pas implémentées de
la même manière (même parfois pas du tout) suivant les constructeurs. Car c’est à la charge du
fabriquant d’écrire les pilotes pour assurer la compatibilité de son matériel avec DirectX : il ne reste
plus qu’à espérer pour le programmeur de jeux vidéo, que ce lien à été réalisé de façon correcte !
DirectX est fourni sous la forme d'un SDK (Software Development Kit). Dans lequel se trouve les
librairies appropriées aux principaux compilateurs (C++, Java, VB), de nombreux exemples de codes,
une aide en ligne volumineuse ainsi que des applications qui permettent de tester le matériel.
DirectX se compose de DirectDraw pour l'affichage 2D, Direct3D pour l'affichage de scène en
3D, de DirectInput pour la gestion des périphériques d'entrée (clavier, souris, manettes de jeux…), de
DirectSound qui gère toute la partie son, de DirectMusic qui s'occupe de la musique de fond (pour
pouvoir rendre une musique dynamique), de DirectShow qui permet l'affichage de vidéo et la lecture
de mp3 et enfin de DirectPlay qui permet de jouer en réseau. Actuellement, nous en sommes à la
version 8 de DirectX. Dans cette version, DirectDraw et Direct3D sont regroupés dans DirectGraphics
ainsi que DirectSound et DirectMusic dans DirectMusic.
Figure 1 : organisation de DirectX
0.2
DirectX possède une compatibilité descendante c'est à dire qu’un programme écrit avec une
version X sera compatible avec les librairies X et ultérieures. Ceci est dû au fait que DirectX est
construit sur le modèle COM : au fur et à mesure des versions, les fonctions ne sont qu’ajoutées et
non remplacées.
Toutes les composantes utilisent des "buffers" autrement dit des tampons de données
contenant diverses informations, et cela en fonction de la nature de la composante (DirectDraw gère
des images, Direct3D des textures, DirectSound des Waves…).
2. DIRECTDRAW
DirectDraw est la composante de DirectX la plus importante, du moment où il est nécessaire
d’afficher des graphismes en plein écran. En effet : elle gère exclusivement l'affichage 2D des surfaces
et les autres modules graphiques (Direct3D, DirectShow…) doivent obligatoirement dialoguer avec elle
pour pouvoir accéder à la surface écran.
Ici nous ne travaillons qu'avec des morceaux d’images appelées « surfaces ». Les opérations
possibles avec ces tampons se limitent à :
- Copies d’images ou morceaux d’images. Les fonctions employées sont dites de « Blitting » :
elles ne peuvent faire que des transferts simples, tout mélange de couleur ou transformation
géométrique est soit impossible, soit bien trop lent du fait de la prise en charge logicielle des
opérations (DirectDraw n’utilise que très peu les fonctions 2D des GPU). De plus, dans notre jeu
nous n’utilisons pas ces fonctions, car elles posent des problèmes de compatibilité avec les
fonctions Direct3D.
- Accès directs en lecture / écriture. DirectDraw nous permet de travailler dans les surfaces
comme dans n’importe quelle zone mémoire. Pour cela il faut auparavant bloquer la surface
avec la fonction « Lock », celle ci retourne un pointeur sur le début de l’image. Le point délicat
réside dans le fait que ces surfaces ont différents formats de pixels : il peut être de 16, 24 ou
32 bits, puis dans ce total on peut répartir différemment les bits pour chaque composante R, G,
B et canal Alpha (A Æ transparence du pixel). De plus, l’organisation des lignes peut être non
linéaire (pour une surface écran de 800x600, la carte vidéo stocke souvent les lignes sur 1024
pixels pour faciliter ses calculs). Malgré cela, nous utilisons la fonction « Lock » lors du
chargement des textures (Disque dur vers surface), et pour lire des pixels sur l’écran.
Figure 2 : les composantes de couleur.
0.3
- La gestion du « double-buffering », Pour l’affichage à proprement parler, nous utilisons deux
types de surfaces : primaire (« FrontBuffer ») et secondaire (« BackBuffer »). Chaque
application écrite avec DirectDraw ne possède normalement qu’une seule surface primaire. En
effet, celle-ci correspond au contenu de l’écran : donc cette surface est directement visible par
l’utilisateur. Pour éviter que la construction de l’image ne soit visible (scintillement), les
opérations graphiques se déroulent exclusivement dans la surface secondaire. Une fois le
rendu de l’image terminé, le programme appelle une fonction DirectDraw : le « Flip » qui
permet d’intervertir la surface primaire avec la surface secondaire donc de l’afficher à l’écran.
Enfin, toutes les surfaces qui ne participent pas directement à l’affichage (autre que primaire et
secondaire) sont appelées surfaces hors-écran (« Off-screen »). Elles servent à stocker les
textures dans notre cas, ou les sprites 2D en général.
Figure 3 : utilisation de DirectDraw, gestion du double-buffering.
3. DIRECT3D
Direct3D est la couche de DirectX permettant de gérer l’affichage de primitives 3D. Tout d’abord
il nous semble important de définir ce que fait réellement Direct3D et ce qui reste à la charge du
programmeur.
Premièrement Direct3D ne possède pas de notions de primitives 3D (Boites, sphères, objets…),
c’était vrai jusqu'à la version 6 si le « mode retenu » était utilisé : mais ce type de fonctionnement
était loin d’être exempt de problèmes (compatibilité, rapidité…), et il à été abandonné à partir de
DirectX version 7.
Ceci précisé, nous pouvons considérer que Direct3D ne sait tracer que des triangles ! Même les
polygones à 4 côtés doivent êtres divisés (« Splités ») pour pouvoir être assimilés (Au contraire de
l’OpenGL).
0.4
A partir de ces triangles représentés dans un espace de dimension 3, Direct3D les rends en
effectuant ce panel d’opérations possibles :
- transformations dans l’espace : en premier lieu il faut passer de la dimension 3 à la dimension
2 caractérisant l’écran : pour cela, lors du rendu, Direct3D effectue la projection des points.
Dans notre cas, s’agissant d’un jeu 2D, nous avons décidé d’oublier la coordonnée Z des points.
L’initialisation du « Viewport » (fenêtre de visualisation) à donc été faîte pour que les
coordonnées (X,Y) des points correspondent aux coordonnées (x,y) de l’écran (projection
orthogonale).
Figure 4 : illustration de la projection orthogonale.
- « Lighting » (illumination) : ceci consiste à calculer (hardware avec les G-Forces, software
sinon) la valeur d’illumination des points des triangles suivant sa normale, sa position et les
caractéristiques des sources lumineuses définies auparavant dans la scène (Objets « Light »).
Cette possibilité est importante pour le réalisme des scènes 3D. Mais, encore une fois, dans le
cadre d’une utilisation 2D nous désactiverons cette fonction (pour chaque tracé de primitive, il
est nécessaire de préciser à Direct3D de désactiver le «Lighting »). Nous aurons aussi des
lampes dynamiques, mais elles seront simulées par des textures.
- Application de texture: Ce qui va suivre explique en grande partie notre choix de développer
notre moteur en utilisant Direct3D. En effet, au contraire de DirectDraw, il est possible de
rendre une surface 2D en l’étirant suivant les points extérieurs. De plus nous pouvons indiquer
à Direct3D d’effectuer un filtrage linéaire des pixels, pour éviter les effets d’escalier en cas de
déformations ou changements d’échelle.
Figure 5 : différence de qualité entre le filtrage linéaire et le « pixel voisin ».
0.5
Les textures elles-mêmes sont des surfaces DirectDraw possédant une interface adéquate.
Comme elles résident le plus souvent en mémoire vidéo et sont directement utilisées par la
carte graphique, les contraintes techniques sont nombreuses. Notamment la taille (largeur et
hauteur) doit être obligatoirement une puissance de deux. De plus, la mémoire vidéo est limitée
(suivant la carte graphique, la présence de l’AGP ou non…), donc nous avons été obligé
d’utiliser, pour les textures, un format de pixel sur 16 bits (le 1-5-5-5 avec un bit pour le canal
alpha) qui ne permet pas de restituer toutes les nuances de couleur.
- Gouraud : Utilisé pour adoucir les transitions des facettes d’objets 3D et pour l’éclairage, le
modèle d’illumination de Gouraud est en fait une interpolation 2D des indices de couleurs situés
aux extrémités du triangle. Nous allons utiliser cette fonction pour simuler l’éclairement de nos
sprites.
Figure 6 : illustration de l’interpolation de couleur qu’effectue le Gouraud entre trois points d’un
triangle possédant des indices de couleurs différents. Ceci sans et avec texture.
- Mélange de couleurs (« Alpha-Blending ») : Cette technique consiste à mélanger la couleur du
nouveau pixel (source) avec le précédant (destinataire) situé sur la surface de rendu. Ceci en
fonction de leurs valeurs RGB et/ou de leurs canaux alpha. Il existe une multitude de
paramètres permettant au programmeur de réaliser la plupart des effets de transparence, mais
aussi de masque et de combinaison. Pour s’en donner une idée veuillez vous reporter à l’annexe
X où un tableau récapitule toutes les combinaisons possibles.
Figure 7 : Un exemple de mélange possible : l’alpha-blending additif , qui est la combinaison la plus
courante : c’est une addition saturée (donc pas d’overflow) entre chaque composante de couleur.
0.6
- L’alpha-testing : Un cas particulier de l’alpha-blending qui permet d’afficher que certains pixels
lors de l’application d’une texture, et cela suivant son canal alpha. Nous utiliserons très souvent
cette possibilité car nos sprites n’occupent pas tout un rectangle mais possèdent un découpage
complexe.
Figure 8 : affichage d’un sprite en utilisant l’alpha-testing qui se sert du canal alpha de la texture
source : le pixel est affiché que si son alpha est au-dessus d’un certain seuil. Comme c’est un choix
binaire nous avons choisi de mettre le canal alpha de toutes les textures sur 1 seul bit.
Bien-sûr, Direct3D propose bien d’autres possibilités (Z-buffer, brouillard…). Mais elles ne
seront pas exposées ici, étant - de part sa nature - totalement ignorées par notre moteur 2D.
Il faut préciser que le moteur 2D, utilisant toutes les techniques décrites ci-dessus, aurait pu
en théorie être directement implémenté de façon logicielle. Mais dans ce cas, malgré une optimisation
parfaite, nous aurions jamais atteint les 30 images par secondes obligatoires pour une animation
fluide des objets à l’écran. En effet la plupart des opérations Direct3D sont directement prises en
charge par la carte graphique dédiée, le processeur ne pouvant avoir une telle rapidité de traitement
pour ces calculs massifs et spécifiques.
Figure 9 : deux screenshots d’une scène du jeu vidéo « Unreal Tournament ». L’un montre le rendu
via Direct3D, l’autre avec uniquement le processeur. Malgré la qualité du rendu logiciel (le meilleur de
sa catégorie), on peut constater que les textures ne sont pas filtrées, les effets de transparence sont
réduits ou supprimés (flare des lampes). De plus, le rendu D3D est extrêmement plus rapide…
En définitive, la plupart des effets de notre jeu, notamment l’alpha-blending, doivent leur
présence à Direct3D (pour son exploitation directe du matériel 3D), dans ce but nous avons construit,
dès le départ, notre moteur 2D autour de cette bibliothèque.
0.7
4. RPG
Le RPG (« Rôle Playing Game ») est une catégorie de jeu à part, au même titre que les
quakes-likes (jeux de tir en vue subjective) ou les simulations de courses… Le principe est assez
simple : vous contrôlez un personnage central, qui évolue à travers un monde immense. Le but est
d’achever des quêtes (tuer dragon, libérer princesse…) tout en faisant évoluer les caractéristiques de
votre personnage : son endurance, force physique, niveau de magie, dextérité, nouveaux sort et
armement…
Un aspect intéressant de ce type de jeu est l’IA : des personnages « intelligents » contribuent
à donner du réalisme et de l’intérêt au jeu. Et cela pour les ennemis, comme pour les autres
protagonistes (marchands, simples passants, compagnons de route…). A ce propos, la référence en
matière de RPG sur ordinateur : « Baldur’s Gate », utilise un système d’IA sophistiqué appelé
« Bioware system », il gère, entre autres, la notion de réputation du personnage et les réactions
complexes de ses compagnons de route…
Mais pour quoi s’être fixé sur ce type de jeu ? Avant de pouvoir répondre, il faut savoir que la
tendance générale dans l’industrie du jeu vidéo est de passer à la « tout 3D ». Mêmes les types de
jeux qui semblaient très bien fonctionner en 2D avec des sprites (comme les jeux de stratégies)
suivent cette tendance (avec des résultats mitigés). Mais heureusement, la plupart du temps, les jeux
de type RPG restent encore en 2D : ceci vient principalement du « gameplay » (façon de jouer)
particulier, qui est plutôt adapté à une vue isométrique lointaine.
De plus, encore très peu de titres utilisent l’accélération 3D des cartes vidéos pour améliorer
les effets 2D et proposer un éclairage dynamique. C’est un challenge qui nous à semblé intéressant de
relever…
Maintenant que nous avons définit le principe du RPG, nous pouvons commencer à énumérer
les principales caractéristiques et les choix effectués dans le cadre de notre jeu :
La vue isométrique : la « caméra » est placée tel que le personnage principal soit toujours centré
à l’écran. On simule en fait une vue de dessus avec un angle de 30° par rapport à l’horizontale du
terrain. Cet angle n’est pas choisi au hasard : 30° permet d’avoir des cases deux fois plus large
que hautes, donc simplifie les calculs par la suite. En effet dans un soucis d’optimisation nous
utiliserons le plus possible des puissance de deux (8 ,16, 32, 64, 128…), avec lesquelles toutes les
multiplications (très coûteuses en temps processeur) pourront êtres remplacées par des décalages
de bits. Par exemple la taille de nos dalles est de 64x32…
- Cases en diamant : pour apporter plus de réalisme, et essayer de camoufler l’utilisation des cases,
nous ne projetons pas directement le terrain parallèlement à x ou y, mais on le tourne de 45°
-
0.8

Documents pareils