// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% // Initiation texture (initialisations, paramétrisations, placage) // TP Prog3D // Fabrice Aubert // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #include #include #include #include "trackball.h" #include "sgi.h" using namespace std; enum {M_JPEG,M_RGB}; //******************************************** // VARIABLES GLOBALES GLint id_tex[4]; // on utilisera 4 textures accessibles par leur identifiant float ax=0.0; // un angle de rotation pour animer les objets de la scène //******************************************* // INITIALISATION DES TEXTURES (affecter une bitmap à un identifiant de texture) // affectation d'une image à un identifiant de texture GLint initTexture(char *nom,int format) { GLubyte *image; // pour stocker les pixels de l'image texture GLuint result; // identifiant de la texture créée GLint longueur,largeur,depthi; switch (format) { case M_JPEG:image=read_jpg(nom,&longueur,&largeur,&depthi);break; case M_RGB:image=read_sgi(nom,&longueur,&largeur,&depthi);break; default:exit(1); } cout << "lecture image " << nom << " : " << longueur << "," << largeur << "," << depthi << endl; // affectation identifiant glGenTextures(1,&result); // génération d'un identifiant par OpenGL glBindTexture(GL_TEXTURE_2D,result); // la texture courante 2D correspond à // l'identifiant result // alignement mémoire du bitmap (indique à OpenGL comment devra être interprété le tableau "image" pour // le mettre dans la mémoire de texture OpenGL (très technique : cf docs OpenGL)). glPixelStorei(GL_UNPACK_ALIGNMENT,1); // affecter la GL_TEXTURE_2D (texture 2D courante) avec une texture (contenue ici dans le tableau "image") // on indique : // - le niveau 0 de mipmap (cf cours) // - le nombre d'éléments consécutifs du tableau "image" qui correspondent à un pixel (GL_RGB=3) // - la longueur et la largeur (en pixels) // - existance d'un bord (sert à d'éventuels recollement de texture bord à bord) : pour nous = 0 (pas de bords) // - quel est le format de la texture (ici GL_RGB) // - le type des éléments du tableau (unigned int) // - le pointeur du tableau constituant la texture (image) glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,longueur,largeur,0,GL_RGB,GL_UNSIGNED_BYTE,image); // la suite indique différents paramètres qui seront donc identiques pour toutes les textures lues. // parametres de repetition en S et T (GL_CLAMP = pas de répétition; GL_REPEAT = répétition). glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); // filtrage texture (cf cours). glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); // mode (ou environement) de calcul de la couleur du fragment : // GL_REPLACE = la couleur du fragment devient la couleur de texture // GL_MODULATE = la couleur de texture est mixee avec la couleur // du fragment (qui contient la couleur donnée par éclairement). // Remarque : malgré le nom glTex*Env*, cela n'a aucun rapport avec "l'environment mapping" glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); return result; } //********************************************* // ACTIVATION-DESACTIVATION des textures // en direct (spécifier les coordonnées par glTexCoord) void textureCoord(GLuint idtex) { // rien d'autre à faire que ce qui a été défini par défaut dans InitTexture glBindTexture(GL_TEXTURE_2D,idtex); glEnable(GL_TEXTURE_2D); } // en automatique par combinaison linéaire (peut-etre interprétée comme projection plane). void textureLinear(GLuint idtex) { // il faut préciser comment est projetée la texture sur les objets : // on spécifie d'abord la formulation de la génération automatique des coordonnées de textures // appliquée en (X,Y,Z). (X,Y,Z) sont les coordonnées 3D du point de l'objet à "texturer". // (X,Y,Z) s'interprèteront dans le repère local à l'objet si on est en GL_OBJECT_PLANE // (X,Y,Z) s'interprèteront dans le repère EYE (global) si on est en GL_EYE_PLANE // S=AX+BY+CZ+DW (ici S=X+0.5) (on présuppose que W sera égal à 1). GLfloat planes[]={2.0, 0.0, 0.0, 0.0}; // 0.5 pour "cadrer" la texture // T=AX+BY+CZ+DW (ici T=Y+0.5) GLfloat planet[]={0.0,2.0,0.0,0.0}; // DW == Décalage glBindTexture(GL_TEXTURE_2D,idtex); // on indique comment sont générés les coordonnées de textures en S et en T glTexGeni(GL_S, GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGenfv(GL_S, GL_EYE_PLANE, planes); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR); glTexGenfv(GL_T, GL_EYE_PLANE, planet); // activation de génération automatique des coordonnées de texture // (les glCoordTex ne sont plus pris en compte). glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_2D); } // en environment mapping (effet de reflexion chrome). void textureEnvironment(GLuint idtex) { // pour l'environment mapping : c'est une génération automatique des coordonnées S et T // cette génération s'effectue par une "sorte" de projection "sphérique" particulière (cf cours). glBindTexture(GL_TEXTURE_2D,idtex); glTexGeni(GL_S,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glTexGeni(GL_T,GL_TEXTURE_GEN_MODE,GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_2D); } // enlève l'application d'une texture void desactiverTexture() { glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glDisable(GL_TEXTURE_2D); } //********************************************** // PRIMITIVES D'AFFICHAGE // 2 quadrilatères orthogonaux void quad(float ax) { glColor3f(1,1,0); glPushMatrix(); glRotatef(ax,1,0.5,0); textureCoord(id_tex[1]); glBegin(GL_QUAD_STRIP); glTexCoord2f(0, 2); glVertex3f(-1.5,-1.5,0); glTexCoord2f(1, 2); glVertex3f(-1.5,+1.5,0); glTexCoord2f(0, 1); glVertex3f(0,-1.5,0); glTexCoord2f(1, 1); glVertex3f(0,+1.5,0); glTexCoord2f(0, 2); glVertex3f(0,-1.5,-1.5); glTexCoord2f(1, 2); glVertex3f(0,1.5,-1.5); glEnd(); desactiverTexture(); glPopMatrix(); } // afficher un plan en Y=0 void sol() { textureCoord(id_tex[0]); // bloc pour les transformations de textures : cf question 4 glMatrixMode(GL_TEXTURE); // on agit sur la matrice de transformation des textures glPushMatrix(); // éviter les effets de bord glTranslatef(0.5, 0.5, 0); glRotatef(ax,0,0,1); // rotation dans l'espace (s,t) des coordonnées de textures glTranslatef(-0.5, -0.5, 0); glMatrixMode(GL_MODELVIEW); // on revient en mode "normal" glColor3f(0,0,1); glBegin(GL_POLYGON); glTexCoord2f(0, 1); glVertex3f(-5,0,-5); glTexCoord2f(1, 1); glVertex3f(5,0,-5); glTexCoord2f(1, 0); glVertex3f(5,0,5); glTexCoord2f(0, 0); glVertex3f(-5,0,5); glEnd(); desactiverTexture(); // bloc transformation de textures glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } void torus(float ax) { textureEnvironment(id_tex[2]); glColor3f(1,0,0); glPushMatrix(); { glRotatef(ax,0.5,1,0.5); glutSolidTorus(0.5,1.5,20,20); } glPopMatrix(); desactiverTexture(); } void boite(float angle) { textureLinear(id_tex[3]); glColor3f(0,1,0); glPushMatrix(); { glTranslatef(-0.4,0.4,0); // petit réglage de position... glRotatef (45, 1, 0, 0); glRotatef(angle,0,1,0.5); glScalef(1.8,1.8,1.8); glutSolidCube(1); } glPopMatrix(); desactiverTexture(); } // ************************************************** // CALLBACKS glut void myDisplay() { glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); glTranslatef(0,-3,-10); tbMatrix(); glPushMatrix(); // sol sol(); // boite glTranslatef(0,4.5,0); boite(ax); // quad (le quad et le tore qui suivent sont placés par rapport à la boite, d'où les push-pop) glPushMatrix(); glTranslatef(-2,-2,0); quad(ax); glPopMatrix(); // tore glPushMatrix(); glTranslatef(2,-2,0); torus(ax); glPopMatrix(); glPopMatrix(); glPopMatrix(); glutSwapBuffers(); } void myMouse(int button, int status, int x, int y) { tbMouse(button, status, x, y); } void myMotion(int x, int y) { tbMotion(x, y); } void myIdle() { ax+=0.5; glutPostRedisplay(); } void myReshape(GLint width,GLint height) { glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,width/height,1,20); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); tbReshape(width,height); } void myKey(unsigned char c,int x,int y) { switch (c) { case 27: exit(0); break; // sortie violente si appui sur "Echap" default: break; } } //******************************** // initialisation opengl void myInit() { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glColorMaterial(GL_FRONT_AND_BACK,GL_DIFFUSE); glEnable(GL_LIGHT0); glEnable(GL_COLOR_MATERIAL); id_tex[0]=initTexture("../data/foret512x256.jpg",M_JPEG); id_tex[1]=initTexture("../data/msmichel.jpg",M_JPEG); id_tex[2]=initTexture("../data/flowers.jpg",M_JPEG); id_tex[3]=initTexture("../data/trois_ages.jpg",M_JPEG); tbInit(GLUT_LEFT_BUTTON); } int main(int argv,char **argc) { glutInit(&argv,argc); glutInitWindowSize(512,512); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH); glutCreateWindow("Textures"); glutReshapeFunc(myReshape); glutDisplayFunc(myDisplay); glutIdleFunc(myIdle); glutKeyboardFunc(myKey); glutMouseFunc(myMouse); glutMotionFunc(myMotion); myInit(); glutMainLoop(); return 0; }