Textures

assets/goal.jpg
Objectif de scène 3D obtenue en fin de séance

Code d'exemple de textures

Considérez désormais le code présent dans le répertoire scenes_inf443/04b_textures/a_texture_uv/

Compilez et exécuter le projet correspondant à ce répertoire. Vous devriez obtenir une scène affichant un quadrangle muni d’une texture.

L'application d'une texture nécessite deux étapes:


Remarques:

Coordonnées de textures

Pour appliquer une texture sur une surface, il est indispensable de définir pour chaque sommets des coordonnées de textures (les coordonnées (u,v)).

Ces coordonnées définissent quelle partie de l'image doivent être appliquées aux sommets de la surface - et par interpolation sur les fragments composant l'intérieur des triangles. Ces coordonnées sont attachées aux sommets en tant que tels (et non pas aux positions 3D (x,y,z)) - Ainsi si vous modifiez les positions de la surface, l'image va s'appliquer sur les mêmes sommets.
Si les triangles de la surface s'étirent (/se compressent), l'image mappée dessus apparaitra également étirée (/compressée).

assets/uv_drawing.jpg
Exemple d'un triangle formé par les points \(p_0, p_1, p_2\) dont les coordonnées de textures sont respectivement données par \(uv_0, uv_1, uv_2\).

Modifiez désormais les coordonnées de textures et tentez d'expliquer le résultat obtenu dans les configurations suivantes

quadrangle_mesh.uv   = { {0,0}, {0.5f,0}, {0.5f,0.5f}, {0,0.5f} };
quadrangle_mesh.uv   = { {0.25,0.25}, {0.5,0.25}, {0.5,0.5}, {0.25,0.5} };
quadrangle_mesh.uv   = { {0,0}, {2,0}, {2,2}, {0,2} };
quadrangle_mesh.uv   = { {0,0}, {1,0}, {1,3}, {0,3} };
quadrangle_mesh.uv   = { {-1,-1}, {2,-1}, {2,2}, {-1,2} };

La fonction opengl_load_texture_image envoie les données de l'image sur le GPU prend en paramètre deux constantes optionnelles qui définissent le comportement d'OpenGL lorsque les coordonnées de textures sortent de l'intervalle [0,1]. Dans le code d'exemple, la constante GL_CLAMP_TO_BORDER est indiquée.

Pour rappel les variables écrites en majuscules sous la forme GL_XXX correspondent à des valeurs prédéfinies dans le standard OpenGL
> Modifiez GL_CLAMP_TO_BORDER en GL_REPEAT et observez le changement de résultat (avec des valeurs de coordonnées (u,v) qui dépassent [0,1]).
assets/texture_repeat_mirror.jpg

Pour d'avantage d'information, vous pouvez regarder le code de la fonction opengl_load_texture_image(image_raw const& im, GLint wrap_s, GLint wrap_t), où vous pourrez y trouver les appels brutes aux fonctions d'OpenGL permettant de paramétrer le comportement des textures. Ces comportements étant paramétrés en particulier par la fonction glTexParameteri.

Coordonnées sur des surfaces

Le fichier models_textures.cpp propose un code de création de tore, cylindre, et disque. Le tore et le cylindre sont des surfaces paramétriques construites de manière similaire au terrain de l'introduction, mais cette fois sous une forme \(f(u,v)=(x(u,v),y(u,v),z(u,v))\). Notez que ces \((u,v)\) sont les coordonnées paramétriques de la surface - ce ne sont pas forcément les coordonnées de textures elles-même.

Pour l'instant ces surfaces n'ont pas de coordonnées de textures spécifiées explicitement.
> Complétez la ligne tore.uv[kv+N*ku] = {?,?}, où les "?" sont des coordonnées à compléter.
Vous pouvez tester une solution naive liée à la paramétrisation de la géométrie tore.uv[kv+N*ku] = {u,v}; et tore.uv[kv+N*ku] = {v,u}; puis adapter ces coordonnées pour reproduire l'image suivante.
assets/torus.png


Similairement, complétez les coordonnées de la fonction de création du cylindre pour obtenir l'apparence texturé suivante

assets/cylinder.png

Par la suite, vous pouvez compléter l'extrémité du cylindre par un disque, et adapter celui-ci de manière à donner l'impression finale d'une buche de bois coupée.

assets/trunk.png assets/trunk_wireframe.png

Application au terrain

Reprenez l'application du terrain et modifiez celle-ci afin d'y plaquer une texture. Pour l'ajout des coordonnées de texture, il est nécessaire de modifier la fonction create_terrain en
assets/terrain_texture.jpg

Bruit de Perlin

Considérez désormais le code présent dans le répertoire scenes_inf443/04b_textures/b_perlin

Ce code applique une déformation de hauteur sur une grille régulière (initialement plane) sous la forme d'un bruit de Perlin. Celui-ci est paramétrable à l'aide des sliders de l'interface.

On rappel que le bruit de Perlin est formé à partir d'une fonction pseudo-aléatoire \(b(p)\) qui a tout point \(p\) renvoit une valeur scalaire déterministe. \(b\) est une fonction lisse à valeur entre \([0,1]\) et non périodique.

Le bruit de Perlin \(P\) est obtenu en sommant plusieurs instances de \(b\) avec des fréquences croissantes, et d'amplitude décroissantes.

\(\displaystyle P(p) = h\;\sum_{k=0} ^ {octaves} \alpha ^ k\,b(\omega ^ k\,p)\)

Les différents paramètres de ce bruit peuvent être manipulés interactivement à l'aide des sliders de l'interface. Retrouvez le rôle de chacun.

Rem.
> Inspirez vous de cette approche pour ajouter un bruit de Perlin à votre terrain déjà existant.
assets/terrain_perlin.jpg

Billboards et objets transparents

Les billboards (ou imposteurs), consistent à utiliser des images d'objets sur fond transparent en tant que texture pour représenter des objets d'apparence complexe sur une géométrie simple (typiquement des quadrangles).

Considérez finalement le code présent dans le répertoire scenes_inf443/04b_textures/c_billboards

assets/billboard_grass.png assets/window_red.png
Texture de brins d'herbes (fond transparent), et fenêtre dont la partie rouge est semi-transparente.


Ces textures sont appliquées de la manière suivante:
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    • - Le buffer de profondeur ne peut en effet pas être utilisé pour afficher les pixels entre objets comportant de la semi-transparence car il empêcherait d'afficher le contenu situé derrière l'objet transparent.
    • - Lors de l'utilisation d'un mélange de couleur, il est donc nécessaire de trier les objets transparents afin d'afficher les objets les plus éloignées d'abord, puis de plus en plus proche de la caméra afin d'accumuler les couleurs dans le bon ordre.

Observez la mise en place de cette approche dans la fonction display_semiTransparent().

Application dans le cas de votre terrain

> Utilisez les billboards pour ajouter des détails à votre scène, par exemple en ajoutant des fleurs et de la végétation sur le terrain.

Exemple possible de terrains avec billboards (les quadrangles ne sont pas triés).
(La texture d'herbe sur le terrain est téléchargeable ici.)