Textures et caméra - TD n°3

Lors de cette scéance, nous abordons la gestion de la caméra en opengl ainsi que la notion de texture.

Exercice 1 : Caméra de la 2D à la 3D

Il faut savoir qu'OpenGL travaille toujours sur des données en 3 dimensions. Cependant nous utilisions jusqu'à maintenant une projection orthogonal en 2 dimensions à l'aide de gluOrtho2D.
Il existe en fait 2 fonctions en OpenGL permettant de gérer les matrices de projections, autrement dis les caméras.

  1. glOrtho(left,right,bottom,top,near,far) qui permet d'obtenir une projection orthogonale.
  2. glFrustum(left,right,bottom,top,near,far) qui permet d'avoir une projection perspective.
Frustum

Pour simplifier les usages les plus courant, GLU fourni 2 autre méthodes utilisant les précédentes :

  1. gluOrtho2D(left,right,bottom,top) qui appele simplement glOrtho avec near=-1 et far=1.
  2. gluPerspective(fovy,aspect,near,far) Qui permet à partir d'un angle et d'un coefficient de simplifier l'utilisation de glFrustum
    • fovy Field Of View on Y axis
    • aspect Aspect ratio : width/height

Vous savez maintenant comment obtenir votre caméra, cependant vous êtes toujours incapable de la placer dans votre scène, vous pouvez uniquement mettre votre scène devant la caméra.
Pour positioner la caméra vous aurez besoin de la fonction :
gluLookAt(eyeX,eyeY,eyeZ,centerX,centerY,centerZ,upX,upY,upZ)

  • eyeXYZ permet de définir la position de l'oeil ( donc de la caméra )
  • centerXYZ est le point fixé
  • upXYZ correspond à la direction du "ciel" pour la caméra

A partir du programme que vous trouverez ICI modifiez la fonction reshapeFunc pour pouvoir voir la différence entre ces différentes configuration de la caméra.

  1. F1 (projection = 0): gluOrtho2D(...);
  2. F2 (projection = 1): glOrtho(...)
  3. F3 (projection = 2): gluPerspective(...)
  4. F4 (projection = 3): glFrustum(...)

Ce programme permet de visualiser un demi-cube, et de ce déplacer dans la scène.

Cube

Exercice 2 - Pile ou Face

Nous allons maintenant voir la notion de Culling.
Pour cela il va falloir dans un premier temps savoir comment activer/desactiver le culling dans opengl.
Les fonctions glEnable(...) et glDisable(...) permettent d'activer et de désactiver un état opengl. Pour activer le culling il faudra donc utiliser :

glEnable(GL_CULL_FACE);
  • En effectuant une rotation autour du cube, que constatez vous?
  • Que pouvez vous en déduire du culling ?
  • Quel en est l'intérêt ?
  • Trouver deux méthodes pour que l'intérieur du cube soit visible

Petit cours - Les textures

Utiliser des textures revient à effectuer deux actions :

  1. Les charger
  2. Les appliquer

I) Chargement d'une texture

Il y a quatres fonctions à connaître :

void glGenTexture(GLsizei n, GLuint *texnames) :
Création de n identifiants uniques de texture.
void glBindTexture(GLenum target, GLuint texname) :
Rend actif l'objet de texture associé à texname. Les opérations suivantes seront donc appliquées à cet objet.
void glTexParameterif(GLenum target, GLenum pname, TYPE param) :
Définie des paramètres de la texture active comme le filtrage des texture.
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, Glenum format, GLenum type, const GLvoid *texels) :
Chargement des données chromatiques texels dans la texture active.

Voici un exemple de création de texture :

...
GLuint texid;
glGenTextures(1,&texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB,
	      width, height, 0, GL_RGB,
	      GL_UNSIGNED_BYTE, data);
...

II) Application d'une texture

Il y a trois fonctions à connaître :

void glBindTexture(GLenum target, GLuint texname) :
rend active la texture identifiée par texname.
void glTexEnvifv(GLenum target, GLenum pname, TYPE param) :
définie la fonction de mélange entre le polygone et la texture.
void glTexCoord1234sifdv(TYPE coords) :
associe une coordonnée de texture à un sommet.

Pour pouvoir appliquer une texture à un polygone, il faut d'abord l'activer en utilisant glEnable() et inversement pour les désactiver glDisable(). De plus il faut savoir que les coordonnées de texture sont normalisées, ainsi pour une image donnée son coin supérieur gauche vaut (0.0,0.0) et son coin inférieur droit vaut (1.0,1.0).

Exemple illustrant l'application d'une texture :

...
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texid);
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f);
glVertex3f(-2.0f, 2.0f, 0.0f);
glTexCoord2f(0.0f,1.0f);
glVertex3f(-2.0f,-2.0f, 0.0f);
glTexCoord2f(1.0f,1.0f);
glVertex3f( 2.0f,-2.0f, 0.0f);
glTexCoord2f(1.0f,0.0f);
glVertex3f( 2.0f, 2.0f, 0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
...

Exercice 3 - Les textures

Pour cet exercice nous utiliserons la fonction glTexEnv de la manière suivante

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

De plus toutes les textures seront à deux dimensions (GL_TEXTURE_2D).

NOTE: Une structure d'image PPM, ainsi que les fonctions d'allocation, désallocation, chargement et sauvegarde est présente dans les fichiers libimage.

Remplissez un tableau d'octets non signés afin de pouvoir créer un damier noir et blanc dont la taille est 8x8. Utilisez ce tableau pour créer une texture RGB et l'afficher entièrement sur l'une des face de votre demi-cube. Pour la spécification des paramètres de texture vous utiliserez :

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
  1. Remplacer GL_NEAREST par GL_LINEAR.
  2. Que se passe-t-il à l'affichage ?
  3. Que pouvez-vous en déduire
  4. Modifiez les coordonnées de texture des sommets de votre carré de manière à avoir la coordonnée (2.0,2.0) en bas à droite.
  5. Que se passe-t-il à l'affichage ?
  6. Remplacez GL_CLAMP par GL_REPEAT, que constatez-vous ?
  7. Que pouvez vous en conclure ?

Maintenant afficher également l'image knight.ppm de l'archive sur une autre face du demi-cube.

Finalement, pour voir si vous avez tout compris, afficher l'image sur la totalité de votre fenêtre opengl. Si vous l'avez fait correctement, l'image doit s'étirer pour s'adapter à la taille de la fenêtre.

Exercice 4 - Si vous avez le temps

Réaliser une fonction drawTexturedSphere(float size,unsigned int nbPoint); qui va créer une sphère de rayon size ayant nbPoint points de contrôle sur chaque axe. Ajouter ensuite un menu permettant d'afficher cette sphère en mode fil de fer ou rempli. Pour finir modifier cette fonction pour pouvoir appliquer une texture à votre sphère.

Si vous avez toujours un peu de temps, faites la même chose pour un cylindre.
Ces deux fonctions vous servirons plus tard.