Le moteur de rendu de terrain

Le moteur de rendu de terrain peut être utilisé pour créer des terrains géants à l'aide des height maps. Il utilise la technique la plus efficace existante pour calculer le rendu de terrains grands et détaillés. Ces méthodes sont nommées geo-mip-mapping et texture splatting. Etant donné qu'il est difficile de comprendre comment utiliser le moteur de rendu de terrain correctement sans connaître comment ces techniques fonctionnent, je vais vous les expliquer maintenant.


Geo-mip-mapping et texture splatting

Ainsi qu'est-ce que le geo-mip-mapping? Il s'agit d'une technique utilisée pour créer efficacement différents niveaux de détails pour les terrains. Le terrain est divisé en un ensemble de carreaux (on nomme cela le tiling) de puissance de deux. Chaque carreau a 5 niveaux de détails différents avec un nombre de triangle allant de 512 à 2. Du fait de la structure efficace des niveaux des LoDs (Niveaux de détails) tous peuvent utiliser le même vertex buffer. La figure suivante illustre à quoi ressemblent les différents niveaux de détails. 

TerrainGeoMipMapping.png

En fonction de la différence de hauteur du carreau et de la distance de la caméra, Ultimate 3D décidera quel niveau de détails utiliser pour afficher le carreau en question. Cette grande variété de LoDs rend le moteur de rendu de terrain incroyablement rapide. Un problème auquel vous êtes fréquemment confronté lorsque vous afficher un terrain, et comment obtenir de bonnes textures pour le terrain. Chaque partie du terrain devrait avoir une couleur différente, mais une texture qui couvre l'ensemble du terrain serait soit extrêmement grande, soit très peu détaillée. Aucune des deux solutions n'est intéressante. Une technique pour éviter cela est l'utilisation d'une carte de détails (detail map), mais cela n'est pas très beau.

C'est pourquoi il existe une technique nommée texture splatting. Lorsque vous utilisez le texture splatting, vous pouvez utiliser autant de textures, étirées sur le terrain (cet étirement correspond aux tiling mais pour les textures), que vous souhaitez. Il vous est donc, ensuite possible d'utiliser les maps alpha pour définir des transparences différentes des textures en différents points. L'image suivante en illustre le fonctionnement:

TerrainTextureSplatting.png

Le texture splatting vous donne la possibilité de rendre votre terrain vraiment détaillé et vivant. Vous pouvez utiliser une texture de pierre pour les collines et des textures d'herbe ou de boue pour les plateaux. Ainsi, vous pouvez également mettre la neige sur les mont de vos montagnes et de plus, mais pas seulement, vous avez la possibilité d'utiliser une texture séparée pour les chemins sur lesquels le personnage peut marcher. Remarquez que le texture splatting requière le support du multi texturing avec, au moins, deux texture simultanées. Cela signifie que la valeur de retour de GetSimultaneousTextureCount() doit être >= 2.


Utiliser le moteur de rendu de terrain

Utiliser le moteur de rendu de terrain est vraiment facile. Le point difficile est de créer les diffuse maps, height maps et les alpha maps (il existe des programme destinés à cela). Mais ce n'est pas le sujet pour le moment. Ici vous apprendrez comment créer un terrain, et comment définir les différentes textures pour ce dernier. Comme avec n'importe quel autre objet Ultimate 3D, un terrain requière son propre objet Game Maker. Et comme d'usage vous devez définir un certain nombre de variables avant de créer le terrain. En voici une liste:

x, y, z
L'origine du terrain. Chaque point sur le terrain aura une coordonée x, y et z qui sera supérieure à la valeur de la variable correspondante.

height_map
Le fichier qui contient la height map que vous voulez utiliser pour créer le terrain. Cela pourrait être, par exemple, "gfx/TerrainHeightMap.png". La height map peut être en niveaux de gris, mais si vous avez besoin de plus de précision, vous pouvez aussi utiliser tous les canaux pour définir la hauteur. La formule utilisée pour convertir une couleur R, G, B, A ayant toutes ses valeurs entre 0 et 255 en une hauteur pour le vertex est z+height*(R*2^24+G*2^16+B*2^8+A)/2^32.

tile_count_x, tile_count_y
Le nombre de carreaux le long de l'axe x et y. Ce sont deux des trois tailles importantes qui donnent la taille du terrain. Elle définissent également à quel point le terrain sera détaillé et combien de temps de calcul et de mémoire sera nécessaire pour calculer son rendu et le créer. Etant donné qu'un terrain est constitué d'une géométrie complexe et détaillée vous ne devriez pas utiliser de trop grandes valeurs ici. 100*100 serait déjà très gros. Sa géométrie prendrait environ 57 MB de RAM.

tile_size
C'est la troisième valeur qui est importante pour la taille du terrain. Elle donne la taille le long de l'axe x et y de chaque carreau dans l'espace. Etant donné que les carreaux sont toujours des carrés, une valeur suffit.

height
La hauteur du terrain. Un pixel noir dans la height map correspondra à la position z sur le terrain égale à la valeur de la variable z, tandis qu'un pixel blanc dans la height map correspondra à une position z sur le terrain, qui sera égale à z+height.

base_texture
Une chaîne de caractères donnant le fichier qui contient la première texture qui est destinée à être appliquée au terrain. Cette texture ne requière pas de map alpha étant donné qu'elle ne recrouvre aucune autre texture.

wrap_count_x, wrap_count_y
L'étirement le long de l'axe x et y pour la première texture. L'étirement est une valeur qui définie à quelle fréquence la texture sera répétée. Habituellement les valeurs de ces variables sont plutôt semblables à celles que vous avez définies pour les variables tile_count_x et tile_count_y.

terrain_lod (optionel)
Le facteur de niveau de détail pour le terrain, qui influence la manière dont Ultimate 3D choisi les LoDs lorsqu'il calcule le rendu des carreaux. Cette valeur est optionelle, vous n'avez donc pas besoin de la définir. Si effectivement elle n'est pas définie, Ultimate 3D utilisera 1 comme facteur de LoD. Si vous définissez une valeur inférieure à 1, des LoDs plus élevés seront utilisés, si vous entrez une valeur supérieure, des LoD's moins élevés seront utilisés.

light_map_resolution (optionnel)
La résolution qui sera utilisée pour la light map (regardez plus bas pour plus d'informations sur les light maps). Par défaut cette variable a 256 pour valeur. Une light map est utilisée pour le terrain tout entier. La valeur pour cette variable doit être une puissance de deux.

alpha_map_resolution (optionnel)
La résolution qui sera utilisée pour la map alpha de chaque carreau. Par défaut, la valeur est de 32. Chaque carreau du terrain a son propre ensemble de maps alpha, donc si vous utilisez de grandes valeurs, cela requèrera beaucoup de mémoire. Une bonne valeur ici, se trouve en général autour de 2*light_map_resolution/(tile_count_x+tile_count_y). La valeur pour cette variable doit être une puissance de deux.


Après la déclaration et la définition de ces variables vous pouvez appeler CreateTerrain(), une seule fois, afin de créer le terrain et l'associer avec l'objet qui a appellé la fonction. Ensuite vous devez ajouter les autres textures au terrain. S'il n'y a pas d'autres textures à appliquer, il vous suffit d'appeler ApplyTerrainTextures(). Etant donné que les terrains sont des objets vraiments statiques, il est inutile de mettre Step() dans l'évènement step cette fois-ci. Cependant, il vous faut toujours mettre Destroy() dans l'évènement correspondant. Si vous voulez utiliser plus d'une texture, à l'aide du texture splatting, il vous faudra mettre d'autres appels de fonctions entre les appels à CreateTerrain() et ApplyTerrainTextures. Etant donné que chaque texture couvre les textures qui ont été appliquées auparavant , l'odre d'appel des fonctions a une influence sur le rendu final. Voici la fonction:

Cette fonction ajoute une texture au terrain par lequel il est appelé, en utilisant le texture splatting:

AddTerrainTexture(
DiffuseMap,
AlphaMap,
WrapCountX, WrapCountY,
AlphaMapChannel
)

DiffuseMap
Une chaîne de caractères donne la fichier contenant la map diffuse que vous voulez ajouter au terrain.

AlphaMap
Une chaîne de caractères indiquant le fichier qui contient la map alpha que vous souhaitez utiliser.

WrapCountX, WrapCountY
L'étirement le long de l'axe x et y pour la map diffuse. Le wrap count est une valeur définissant à quelle fréquence la texture doit être répétée. Pour qu'il soit moins évident de voir que la texture se répète, vous devriez utiliser des étirements différents pour les différentes textures.

AlphaMapChannel
La canal de la map alpha, dont on va récupérer les données. Cela peut être 0 pour utiliser la luminosité (pour les maps alpha en niveaux de gris), 1 pour utiliser le canal rouge, 2 pour utiliser le canal vert, 3 pour utiliser le canal bleu ou 4 pour utiliser le canal alpha. Grâce à ce paramètre un  même ficher de map alpha peut contenir les maps alphas de plusieurs maps diffuses.

Voilà donc, tout ce que vous devez savoir sur la création de terrains. Avec ces quelques fonctions vous pouvez créer des paysages géants déjà bien détaillés. Cela ne serait pas possible avec des modèles de terrains usuels. Le moteur de rendu de terrain est donc destiné aux gens souhaitants créer des jeux avec de nombreux grands niveaux se jouant à l'exétérieur.

Il existe également deux fonctions utiles pour récupérer des données à propros d'un objet de terrain à une position donnée. L'une d'elle permet de récupérer la hauteur du terrain à une position particulière, et l'autre peut être utilisée pour savoir quelle texture est utilisée à quelle force à une poistion particulière. Voici leurs descriptions:

Cette fonction retourne la hauteur d'un objet de terrain donné à une position donnée. Elle prend très peu de temps de calcul.

GetTerrainHeightAtPos(
TerrainID,
X, Y
)

TerrainID
L'ID de l'objet de terrain dont vous souhaitez retrouver une valeur de hauteur.

X, Y
La position pour laquelle vous souhaitez déterminer la hauteur.


Cette fonction retourne l'intensité d'une texture donnée à la position spécifiée, du terrain donné. La valeur de retour est un réel allant de 0 à 1, où 0 signifie que la texture ne peut être vue à cet endroit et 1 signifie que la texture est la seule pouvant être vue à cette position.

GetTextureStrengthAtPosition(
TerrainID,
TextureIndex,
X, Y
)

TerrainID
L'ID de l'objet de terrain dont vous voulez retrouver l'intensité de la texture.

TextureIndex
L'indice de la texture dont vous voulez récupérer des informations. 0 se réfère la diffuse map de base, 1 se refère à la première texture ajoutée et ainsi de suite.

X, Y
La position pour laquelle vous voulez connaître l'intensité de la texture.

Ces deux fonctions sont très utiles. La première peut être utiliser pour une detection simple et efficace des collisions avec le terrain, la deuxième peut être utilisée pour déterminer la matière présente à tel endroit. Si vous souhaitez mettre de la végétation sur un terrain vous pouvez utiliser GetTextureStrengthAtPosition(...) pour ne pas créer de végétation sur les rocher ou sur les routes.

Calculer la light map

Si vous avez déjà créé un terrain vous avez peut être remarqué qu'il n'est pas éclairé par les sources de lumières. Vous devriez en être heureux; car cela serait affreux si le vertex lighting était utilisé parce que le nombre de vertex de chaque carreaux change lorsque le LoD change. Et étant donné que l'oeil humain est très sensible aux changements rapides, cela ne donnerait rien d'esthétique. C'est pourquoi les terrains utilisent une light map à la place. Une light map est une texture qui est appliquée sur tout le terrain à l'aide d'une opération de texture multiplicatrice. Remarquez que cela requière le support du multi texturing avec trois textures, ainsi la valeur de retour de GetSimultaneousTextureCount() doit être >=3.

Ultimate 3D calcule la light map automatiquement. Il vous suffit de lui dire quelles sources de lumières doivent être utilisées pour créer la light map. Souvent, il n'est pas bon d'utiliser des sources de lumières qui bougent beaucoup pour calculer la light map, parce que la recalculer à chaque frame prend énormément de temps de calcul. Vous devriez donc n'utiliser que les sources de lumière qui ne changent pas rapidement. Je vous conseille d'utiliser une morceau de code qui dit à Ultimate 3D de recalculer la light map fréquemment (par exemple une fois pas seconde). Voici la fonction dont vous avez besoin pour faire calculer la light map par Ultimate 3D.

Cette fonction dit à Ultimate 3D de recalculer la light map pour l'objet de terrain qui appelle la fonction.

CalculateTerrainLightMap(
LightSourceID1, LightSourceID2, ..., LightSourceID10
)

LightSourceID1, LightSourceID2, ..., LightSourceID10
Les identifiants Game Maker des objets de source de lumière que vous souhaitez utiliser pour calculer la light map. Si vous mettez 0 pour chacun d'eux, Utilmate 3D utilisera toutes les sources de lumière qui font partie de la scène.

Si la fonction de calcul de light map intégrée ne satisfait pas vos attentes, ce n'est pas un problème. Ultimate 3D vous permet d'utiliser votre propre light map à la place.  Vous la créer dans n'importe quelle logiciel d'édition d'image ou dans un programme tel que Earth Sculptor. De cette manière vous pouvez utiliser des lights maps avec des ombres précalculées ou avec toute autre méthode de calcul. S'il y a une forêt quelque part sur votre terrain vous pouvez assombrir votre light map à cet endroit, pour obtenir un sol ombragé. Des choses comme celle-ci ne peuvent être faites efficacement sans avoir la possibilité de définir vos propres lights maps. Donc, comme vous pouvez le voir, cette fonction est très puissante.

Cette fonction va définir une texture comme light map de votre terrain.

SetCustomTerrainLightMap(
TextureIndex
)

TextureIndex
L'indice de la texture, qui sera définie comme nouvelle light map pour le terrain. Si vous souhaitez revenir à la light map calculée automatiquement, vous pouvez passer un indice inutilisé à ce paramètre.

Déformer un terrain

Dans les jeux proposant des armes lourdes, vous n'irez nulle part sans déformer le terrain quelques fois. Si une bombe explose, un cratère doit être créé. Cela peut contribuer directement au game play, étant donné que le joueur pourra peut être se cacher dedans ensuite. Ultimate 3D offre une fonction vraiment très simple pour la déformation des terrains, qui donne le résultat souhaité dans la plupart des cas. 

Cette fonction aggrandi ou rapetissi le terrain autour de la position donnée.

DeformTerrain(
DeformationCenterX, DeformationCenterY,
DeformationRadius,
RaiseLevel
)

DeformationCenterX, DeformationCenterY
L'origine de la déformation dans le niveau. C'est la position à laquelle la déformation sera la maximale.

DeformationRadius
Le rayon autour de l'origine de déformation, dans lequel le terrain sera déformé.

RaiseLevel
Le niveau de déformation du terrain, définissant de combien le terrain sera relevé (valeur positive) ou abaissé (valeur négative).

À l'origine de la déformation, le terrain est relevé ou abaissé par RaiseLevel, et à une distance supérieure ou égale à DeformationRadius le terrain ne change pas. Dans cet intervale une courbe cosinoïdale est utilisé pour obtenir une forme lisse. Le graphique suivant en illustre le principe.

Illustration not available

Cette méthode donne des cratère sphériques très sympas. Elle est suffisamment rapide pour être appellée pendant le gameplay, mais elle ne devrait pas être appellée à chaque step ou trop fréquemment. Remarquez que cette méthode ne peut abaisser les terrain en dessous de z et ne peut pas les élever au dessus de z+height. Si vous utilisez cette méthode, vous devriez être sûr qu'il y ait un peu de place avant que les limites ne soient atteintes.

Création de décalcomanie sur le terrain

Souvent il peut être utile de couvrir le terrain avec d'autres textures à certains endroits. Par exemple aux endroits où une explosion a eu lieue, une texture avec de la terre brûlée pourrait apparaître. Le texturage du terrain lui même ne peut être changé, mais il est possible de créer des textures superposées sur le terrain, qui le couvre parfaitement et utilisent la texture désirée. Ces superpositions sont nommées décalcomanies de terrains. Ultimate 3D permet la création automatiquie de décalcomanie pour les terrains. Les décalcomanies de terrains sont des objets de modèle et de fait ils requièrent leur propre objet Game Maker. Dans cet objet vous devrez définir quatres variables avant la création du décalcomanie:

terrain_object
L'ID de l'objet de terrain sur lequel vous souhaitez créer une décalcomanie.

center_x, center_y
Le position centrale de la décalcomanie dans le niveau.

size
La taille de la décalcomanie. Les décalcomanies de terrain sont toujours des carrés, à moins qu'elles aient besoins d'être recadrées lorsqu'elles sont au bord du terrain.

Après avoir défini ces variables, vous pouvez appeller CreateTerrainDecal(), afin de dé créer la décalcomanie. Comme d'usage il vous faut appeller Destroy() dans l'évènement destroy. Et Step() peut être appellé dans l'évènement step, mais d'usage ce n'est pas nécessaire étant donné que les décalcomanies de terrain sont statiques. Modifier les les variables de transformation n'est généralement pas souhaité. Les variables x, y, z, rotx, roty et rotz devrait être égales à zero et scalx, scaly et scalz devraient être égales à un. Sinon le terrain sera à la mauvaise place.

L'objet de modèle créé peut être modifié comme tout autre objet de modèle. Vous pouvez utiliser SetMaterialStageTexture(...) pour lui fournir une texture, vous pouvez utiliser SetModelMaterial(...) pour changer sa couleur et vous pouvez même modifier sa géométrie avec les fonctions de manipulation de modèles. L'objet a plusieurs niveaux de détails de façon à ce qu'il corresponde exactement à la forme du terrain, sans que le LoD actuel de cette partie du terrain n'y change quoi que ce soit. Cela fonctionne vraiment bien, mais il peut quand même encore arriver parfois que la décalcomanie soit couverte par le terrain. Dans ce cas vous pouvez un peu augmenter la valeur de la variable z et appeller Step(). Cela réglera le problème. C'est à vous de trouver la valeur parfaite pour z. Cela dépend du terrain et de la taille de la décalcomanie.


Création de height map et de map alpha

Pour la création de height maps et de maps alpha, je peux vous conseiller un programme très convivial, nommé Earth Sculptor. Son utilisation est très intuitive et il est disponible avec un manuel détaillé. Malheureusement la version non enregistrée est un peu limitée. Une fois que vous aurez dessiné un terrain dans Earth Sculptor vous pourrez le sauvegarder. Le programme sauvegardera ensuite une height map, une map alpha compressée, et une light map. La height map peut être utilisée par Ultimate 3D telle qu'elle. Vous pouvez aussi utiliser la light map en tant que light map personnalisée si vous le souhaitez. La map alpha peut aussi être utilisée si elle est exportée grâce au paramètre AlphaMapChannel de AddTerrainTexture(...).

D'autres programmes gratuits permettant la création de terrains sont Terragen, World Machine, Terranim8or et L3DT. Une explication sur comment exporter les heights maps depuis Terranim8or est disponible sur la communauté Ultimate 3D et un turorial sur l'utilisation de L3DT par Ruud v A peut être lu dans le Wiki d'Ultimate 3D.



© Christoph Peters. Certains droits réservés. (Traduction FR 04/2008, Franck Vernel / Damien Buhl).

Creative Commons License XHTML 1.0 Transitional