// Test fragment : un exemple simple sur le stencil (cache // pour simuler un <> dans un polygone) // Prog3D // Fabrice Aubert #include #include #include #include "trackball.h" #include using namespace std; static void erreur(const string &mesg) { cout << "Erreur dans stencil.cpp :" << endl; cout << mesg << endl; exit(1); } // *********************************************************** // VARIABLES GLOBALES (textures, animation) GLint tex_id; // identificateur de texture GLuint image_id; // Variables globales pour la cinématique de la scène (voir myIdle) GLfloat angScene=0.0; // angle de rotation de la scene //***************************************************************** // INITIALISATIONS ET ACTIVATION TEXTURES GLint initTexture(const char *nom) { GLubyte *image; GLuint result; GLint longueur,largeur,format,bpp,depth; ILenum il_erreur; bool ok=ilLoadImage(nom); if (!ok) { cout << "impossible de lire " << nom << endl; erreur("initTexture"); } longueur=ilGetInteger(IL_IMAGE_WIDTH); largeur=ilGetInteger(IL_IMAGE_HEIGHT); format=ilGetInteger(IL_IMAGE_FORMAT); bpp=ilGetInteger(IL_IMAGE_BYTES_PER_PIXEL); cout << "lecture image " << nom << " : " << longueur << "," << largeur << "," << bpp << endl; image=new GLubyte[longueur*largeur*bpp]; // Attention : memory leak ! ilCopyPixels(0,0,0,longueur,largeur,1,IL_RGB,IL_UNSIGNED_BYTE,image); il_erreur=ilGetError(); if (il_erreur!=IL_NO_ERROR) { // cout << iluErrorString(il_erreur); erreur("Chargement texture"); } // affectation identifiant glGenTextures(1,&result); // génération d'un identifiant par OpenGL glBindTexture(GL_TEXTURE_2D,result); // la texture courante 2D correspond à glPixelStorei(GL_UNPACK_ALIGNMENT,1); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,longueur,largeur,0,GL_RGB,GL_UNSIGNED_BYTE,image); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); return result; } // ************************************************************************ // AFFICHAGE DES PRIMITIVES void tracerPlanTexture() { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,tex_id); glBegin(GL_POLYGON); glTexCoord2f(0.0,0.0);glVertex3f(-5,-5,0); glTexCoord2f(1.0,0.0);glVertex3f(5,-5,0); glTexCoord2f(1.0,1.0);glVertex3f(5,5,0); glTexCoord2f(0.0,1.0);glVertex3f(-5,5,0); glEnd(); glDisable(GL_TEXTURE_2D); } void tracerTrou() { glBegin(GL_POLYGON); glVertex3f(0,3,0); glVertex3f(3,0,0); glVertex3f(0,-3,0); glVertex3f(-3,-1.5,0); glVertex3f(-3,2.7,0); glEnd(); } // **************************************************************** // LES EVENEMENTS : myDraw, myReshape, myIdle void myDisplay(void) { glClearColor(1,1,1,0); glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glPushMatrix(); glTranslatef(0,0,-15); tbMatrix(); glRotatef(angScene,1,1,0); // Rappel des instructions du stencil : // Activation de l'exploitation du stencil (en test et mise à jour). // glEnable(GL_STENCIL_TEST); // Modification du test : // glStencilFunc(Opérateur, Référence, Masque) spécifie le test du stencil : // le test du stencil passe si // (Reference & Masque) (valeur du stencil destination & mask) // Remarque : // glStencilFunc(GL_ALWAYS,0x1,0x1); // indique que le test réussi toujours // (autrement dit : le test est désactivé) // glStencilOp précise les mises à jour // glStencilOp(Maj1, Maj2, Maj3). // (Exemple : désactivation de la mise à jour : // glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); glEnable(GL_STENCIL_TEST); glClear(GL_STENCIL_BUFFER_BIT); // tracé du polygone représentant le trou glPushMatrix(); //glTranslatef(0,0,0.1); // léger décalage pour éviter le z-fighting // Désactivation de la MAJ du Depth et Color buffers glDepthMask(GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Marquer 1 à tous les pixels glStencilFunc(GL_ALWAYS, 1, 1); glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); tracerTrou(); // Réactivation de la MAJ du Depth et Color buffers glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDepthMask(GL_TRUE); // Désactiver la MAJ du stencil glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP); glPopMatrix(); /*** TRACE LE PLAN ***/ // Trace que si on n'a pas de un glStencilFunc(GL_EQUAL, 0, 1); tracerPlanTexture(); // Désactive le test du stencil glStencilFunc(GL_ALWAYS, 1, 1); // deux objets : glPushMatrix(); glTranslatef(-2,-1,3); // sphère "devant" le plan glColor3f(1,0.5,0.2); glutSolidSphere(1.5,10,10); glPopMatrix(); glPushMatrix(); glTranslatef(2,1,-3); // sphère "derriere" le plan glColor3f(0.5,1.0,0.2); glutSolidSphere(1.5,10,10); glPopMatrix(); glPopMatrix(); glutSwapBuffers(); } void myReshape(GLint width,GLint height) { glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45,(GLfloat)width/height,1,30); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); tbReshape(width, height); } void myIdle(void) { //angScene+=1.0; tbIdle(); glutPostRedisplay(); } // CallBack clavier void myKey(unsigned char c,int x,int y) { switch (c) { case 27: exit(0); break; // sortie violente si appui sur "Echap" default: break; } } // Callback de la souris void myMouse(int button, int status, int x, int y) { tbMouse(button,status,x,y); } void myMotion(int x,int y) { tbMotion(x,y); } // ***************************************************** // INITIALISATION OPENGL (+lecture texture+lecture objet) void myInit() { ilInit(); image_id=ilGenImage(); ilBindImage(image_id); ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT); glEnable(GL_DEPTH_TEST); glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE); glEnable(GL_COLOR_MATERIAL); tex_id=initTexture("../data/msmichel.jpg"); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); tbInit(GLUT_LEFT_BUTTON); } main(int argv,char **argc) { glutInit(&argv,argc); glutInitWindowSize(512,512); glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL); glutCreateWindow("Prog 3D - Stencil"); glutReshapeFunc(myReshape); glutDisplayFunc(myDisplay); glutIdleFunc(myIdle); glutKeyboardFunc(myKey); glutMouseFunc(myMouse); glutMotionFunc(myMotion); myInit(); glutMainLoop(); }