OpenGL:Glow
Un article de Games Creators Network.
Dans cet article, nous allons traiter d'une technique coûteuse mais gratifiante : l'effet de halo, ou glow.
Pour ce faire, nous utiliserons l'extension GLU, l'API Win32, ainsi que le compilateur de l'IDE Dev-C++. Néanmoins, cet exemple pourra être utilisé avec n'importe quel autre gestionnaire de fenêtre, ou compilateur, sous réserve d'y apporter quelques modifications.
Le modèle de base de notre application est extrait du site NeHe. Pour plus d'explications sur ce type d'application OpenGL avec Win32, consultez NeHe.gamedev.net.
Nous utiliserons aussi la bibliothèque de chargement de fichier Targa de Nate Miller pour nos textures.
Un exemple du rendu de notre programme est visible sur l'image de droite. Avec un cube texturé blanc, et un cube texturé avec un effet de glow en couleur.
Sommaire |
[modifier] Avant toute chose
Nous devons définir les bibliothèques que nous allons utiliser, y compris celle de chargement des fichiers Targa.
/***************************************************** * FICHIERS EN-TETE * ******************************************************/ #include <windows.h> // Windows #include <gl\gl.h> // OpenGL #include <gl\glu.h> // OpenGL Utility #include "tga.h"
Nous allons aussi déclarer une variable float Rot, qui nous servira à faire tourner notre cube, pour mieux apprécier l'effet. Nous déclarons aussi une variable de type entier textureGlow, qui contiendra l'identifiant de la texture de glow.
/***************************************************** * DECLARATIONS DES VARIABLES * ******************************************************/ float Rot = 0; // rotation du cube int textureGlow; // identifiant de la texture de glow
Nous allons aussi en profiter pour pré-déclarer nos fonctions
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); GLuint EmptyTexture( void ); void RenderToTexture( void ); void RenderGlow( int times ); void RenderCube( void );
[modifier] Initialisation d'OpenGL
Commençons notre article en analysant notre initialisation d'OpenGL. Il n'y a aucune nouveauté, si ce n'est que nous chargeons une texture pour notre cube, et une autre pour notre texture de glow.
int InitGL(GLvoid) { glShadeModel(GL_SMOOTH); glClearColor(0.0f, 0.0f, 0.0f, 0.5f); glClearDepth(1.0f); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); loadTGA("GCN.tga",1); // Chargement de la texture du cube textureGlow = EmptyTexture(); return TRUE; }
[modifier] Création de la texture
Pour stocket notre texture de glow, il va d'abord falloir la créer, voici donc le but de cette fonction.
GLuint EmptyTexture( void ) { GLuint txtnumber; unsigned int* data; // On alloue de la place pour notre texture de 512x512 data = (unsigned int*)new GLuint[((512 * 512)* 4 * sizeof(unsigned int))]; // On nettoie les données en les remplissant de 0 ZeroMemory(data,((512 * 512)* 4 * sizeof(unsigned int))); glGenTextures(1, &txtnumber); // On génère un identifiant glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, txtnumber); // On effectue la première passe glTexImage2D(GL_TEXTURE_2D, 0, 4, 512, 512, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); delete [] data; glDisable(GL_TEXTURE_2D); return txtnumber; }
[modifier] Génération de la texture de glow
Il va maintenant falloir commencer à se pencher sur l'effet de glow.
En fait, cet effet est assez simple, le but est de copié le contenu de l'écran dans une texture, puis ensuite de plaquer cette texture de nombreuses fois à l'écran, tout en la grossissant, et en la rendant transparente.
Nous allons donc ici copié le contenu de l'écran vers notre texture grace à la fonction glCopyTexImage2D.
void RenderToTexture( void ) { RenderCube( ); //On dessine notre cube glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, textureGlow); //On selectionne notre texture de glow // Et on copie le contenu de l'écran vers la texture glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 512, 512, 0); glClearColor(0., 0., 0., 0.); // On efface l'écran avec du noir glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_TEXTURE_2D); //On deselectionne notre texture }
[modifier] Dessin du glow
Maintenant que nous avons notre "texture de scène", il va falloir la plaquer sur l'écran. C'est le but de cette fonction.
void RenderGlow( int times ) { //On se projette en vision orthogonale (2D) glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho( 0, 512 , 0, 512, -1, 1 ); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,textureGlow); // On selectionne notre texture glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // activation de la transparence glBegin(GL_QUADS); for (int i=0; i<times; i++) { glColor4f(1., 1., 1., 0.3/(float)i); //Transparence croissante (amusez vous avec) glTexCoord2f(0+((float)i/75.f),0+((float)i/75.f)); // on "écarte" notre glVertex2f(0,0); // texture progressivement glTexCoord2f(0+((float)i/75.f),1-((float)i/75.f)); glVertex2f(0,512); glTexCoord2f(1-((float)i/75.f),1-((float)i/75.f)); glVertex2f(512,512); glTexCoord2f(1-((float)i/75.f),0+((float)i/75.f)); glVertex2f(512,0); } glEnd(); // On repasse en vision en perspective glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix(); glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D,0); }
[modifier] Rendu de notre cube
Cette fonction se passe de commentaires, nous dessinons notre cube texturé, lui ajoutons quelques dégradés de couleurs, et le faisons tourner.
void RenderCube( void ) { glPushMatrix(); glEnable(GL_DEPTH_TEST); glRotatef(Rot,1,1,0); glScalef(10,10,10); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, 1); glBegin( GL_QUADS ); //FACE 1 glColor4f(0.,1.,1.,1.); glTexCoord2d(1,1); glVertex3i(1,1,1); glColor4f(1.,0.,1.,1.); glTexCoord2d(1,0); glVertex3i(1,-1,1); glColor4f(1.,1.,0.,1.); glTexCoord2d(0,0); glVertex3i(-1,-1,1); glColor4f(1.,0.,1.,1.); glTexCoord2d(0,1); glVertex3i(-1,1,1); //FACE 2 glColor4f(0.,1.,1.,1.); glTexCoord2d(0,0); glVertex3i(1,1,-1); glColor4f(1.,0.,1.,1.); glTexCoord2d(1,0); glVertex3i(1,-1,-1); glColor4f(1.,1.,0.,1.); glTexCoord2d(1,1); glVertex3i(-1,-1,-1); glColor4f(1.,0.,1.,1.); glTexCoord2d(0,1); glVertex3i(-1,1,-1); //FACE 3 glColor4f(0.,1.,1.,1.); glTexCoord2d(0,0); glVertex3i(1,1,1); glColor4f(1.,0.,1.,1.); glTexCoord2d(1,0); glVertex3i(1,-1,1); glColor4f(1.,1.,0.,1.); glTexCoord2d(1,1); glVertex3i(1,-1,-1); glColor4f(1.,0.,1.,1.); glTexCoord2d(0,1); glVertex3i(1,1,-1); //FACE 4 glColor4f(0.,1.,1.,1.); glTexCoord2d(0,0); glVertex3i(-1,1,1); glColor4f(1.,0.,1.,1.); glTexCoord2d(0,1); glVertex3i(-1,-1,1); glColor4f(1.,1.,0.,1.); glTexCoord2d(1,1); glVertex3i(-1,-1,-1); glColor4f(1.,0.,1.,1.); glTexCoord2d(1,0); glVertex3i(-1,1,-1); //FACE 5 glColor4f(0.,1.,1.,1.); glTexCoord2d(0,0); glVertex3i(-1,1,-1); glColor4f(1.,0.,1.,1.); glTexCoord2d(1,0); glVertex3i(-1,1,1); glColor4f(1.,1.,0.,1.); glTexCoord2d(1,1); glVertex3i(1,1,1); glColor4f(1.,0.,1.,1.); glTexCoord2d(0,1); glVertex3i(1,1,-1); //FACE 6 glColor4f(0.,1.,1.,1.); glTexCoord2d(0,0); glVertex3i(-1,-1,-1); glColor4f(1.,0.,1.,1.); glTexCoord2d(1,0); glVertex3i(-1,-1,1); glColor4f(1.,1.,0.,1.); glTexCoord2d(1,1); glVertex3i(1,-1,1); glColor4f(1.,0.,1.,1.); glTexCoord2d(0,1); glVertex3i(1,-1,-1); glEnd(); glDisable(GL_TEXTURE_2D); glPopMatrix(); Rot += 1; }
[modifier] Rendu de la scène
Nous pouvons maintenant rendre notre scène simplement en appelent RenderToTexture puis RenderGlow avec comme paramètre le nombre de passes du glow.
int DrawGLScene(GLvoid) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glLoadIdentity(); gluLookAt(75,75,75,0,0,0,0,1,0); RenderToTexture(); RenderGlow(20); return TRUE; }
[modifier] Téléchargements
Télécharger les sources + l'exécutable
--NewbiZ 25 aoû 2005 à 01:39 (CEST)


