logo

Creer un projet OpenGL

C'est ici que vous posterez vos questions sur la programmation windows (fenetres, boutons...)

Creer un projet OpenGL

Messagede Tibo » 12 Mai 2008, 12:29

Il y a quelques années, lorsque j'ai commencé à programmer, les jeux 3D m'ont fasciné. Quand j'ai eu les connaissances suffisantes pour créer des petits jeux, je me suis intéressé à la SDL (une librairie simple pour faire des jeux 2D). Mais je me suis rapidement rendu compte que derrière la simplicité de la librairie se cachait un gros problème : les performances...
Se basant sur DirectX5 (époque de windows 95 :( ), dès que l'on utilise de la transparence ou qu'on affiche plein de trucs à l'écran, ça devient très vite saccadé... Je me suis alors penché sur OpenGL, et je fus vite conquis !
OpenGL se base sur un principe de caméra et d'objets 3D. Il est tout à fait possible de faire un jeux en 2D (comme le montre le projet d'un de mes étudiants) en plaçant une caméra pour qu'elle fasse une "vue du dessus".
Pour vous aider à commencer la programmation 3D, j'ai rédigé quelques posts à la suite...
Tibo
Administrateur du site
 
Messages: 147
Inscription: 26 Mar 2008, 13:58

Utiliser la bibliothèque OpenGL

Messagede Tibo » 12 Mai 2008, 12:31

Pour répondre aux problèmes courants lors de la création de fenêtres OpenGL, voici un certain nombre de conseils (valables pour toutes versions de Visual Studio).
Dans les propriétés du projet, il faut :
  • Dire au compilateur que l'on utilise des DLL multi-thread :
    Code: Tout sélectionner
    Configuration Properties->C/C++->Code Generation->Runtime Library : Multi-threaded DLL
  • Dire au linker que l'on utilise des DLL d'OpenGL :
    Code: Tout sélectionner
    Configuration Properties->Linker->Input->Additionnal Dependencies : opengl32.lib glu32.lib
  • Utiliser les entêtes des librairies d'openGL :
    #include <gl/gl.h>
    #include <gl/glu.h>
    Attention : glut.h est à éviter car il n'est plus mis à jour !

Ensuite, pour simplifier l'utilisation des textures, je vous recommande d'utiliser DevIL. Son incorporation dans Visual n'est pas beaucoup plus complexe. De même que pour OpenGL, il faut :
  • Dire au compilateur que l'on utilise des DLL multi-thread :
    Code: Tout sélectionner
    Configuration Properties->C/C++->Code Generation->Runtime Library : Multi-threaded DLL
  • Dire au linker que l'on utilise des DLL de DevIL:
    Code: Tout sélectionner
    Configuration Properties->Linker->Input->Additionnal Dependencies : DevIL.lib ILU.lib ILUT.lib
  • Utiliser les entêtes des librairies d'openGL :
    #include <IL/il.h>
    #include <IL/ilu.h>
    #include <IL/ilut.h>
  • Ajouter les fichiers .h de Devil dans le répertoire d'installation de Visual :
    Code: Tout sélectionner
    Pour moi : C:\Program Files\Microsoft Visual Studio 9.0\VC\include
  • Ajouter aussi les fichier .lib de Devil :
    Code: Tout sélectionner
    Pour moi : C:\Program Files\Microsoft Visual Studio 9.0\VC\lib

Si vous voulez utiliser à la fois DevIL et OpenGL, pensez à mettre toutes les dépendences (opengl32.lib glu32.lib DevIL.lib ILU.lib ILUT.lib)
Normalement, si vous avez tout respecté, ça devrait marcher... N'hésitez pas à poster vos erreurs si ça ne marche pas !
Tibo
Administrateur du site
 
Messages: 147
Inscription: 26 Mar 2008, 13:58

Créer une fenêtre OpenGL

Messagede Tibo » 12 Mai 2008, 13:02

Pour créer une fenêtre OpenGL, il y a deux possibilités :
  • utiliser GLUT qui permet de s'affranchir de détails techniques propres à Windows (ou linux...). Le but du post ici n'est pas de faire un tutorial sur GLUT, utilisez celui là qui est très bien fait !
  • utiliser les fonctions de Windows.
C'est cette deuxième version que nous allons détailler.

Tout d'abord, relisez bien mes cours sur Windows pour que l'on parte sur les mêmes bases...
Je suppose donc que vous avez compris l'intérêt de la fonction MainProc...

Pour commencer, créons une fenêtre OpenGL... On ne va pas faire comme dans mon cours car on veux pouvoir la paramétrer plus en détails...
Voila le code pour créer une fenêtre OpenGL :
Code: Tout sélectionner
BOOL fenetre::CreeGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
   GLuint      PixelFormat;
   WNDCLASS   wc;
   DWORD      dwExStyle;
   DWORD      dwStyle;
   RECT      WindowRect;
   WindowRect.left=(long)0;
   WindowRect.right=(long)width;
   WindowRect.top=(long)0;
   WindowRect.bottom=(long)height;
// Met a jour l'info de fullscreen
   fullscreen=fullscreenflag;         
// Recupere l'instance de la fenetre
   hInstance         = GetModuleHandle(NULL);   
// Redessine si modification de la taille ou de la position et garde un seul DC pour la fenetre.         
   wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
// fonction de traitement des messages (voir mon cours)
   wc.lpfnWndProc      = (WNDPROC) fenetre::MainProc;
   wc.cbClsExtra      = 0;                           
   wc.cbWndExtra      = 0;                           
   wc.hInstance      = hInstance;
// Icone par default         
   wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
// Curseur par default   
   wc.hCursor         = LoadCursor(NULL, IDC_ARROW);
// Pas de fond pour Opengl (c'est justement lui qui dessinera le fond)
   wc.hbrBackground   = NULL;
// On ne veut pas de menu
   wc.lpszMenuName      = NULL;
// Nom de la fenetre
   wc.lpszClassName   = "OpenGL";
// Essaye de creer la class fenetre :
   if (!RegisterClass(&wc))
   {
      MessageBox(fenetre::hWnd,"Impossible de cree la class fenetre....","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   if (fullscreen)// Est on en plein ecran?
   {
//oui, alors on passe la fenêtre en fullscreen...
      DEVMODE dmScreenSettings;
      EnumDisplaySettings(NULL,ENUM_CURRENT_SETTINGS,&dmScreenSettings);
      dmScreenSettings.dmSize=sizeof(dmScreenSettings);
      dmScreenSettings.dmPelsWidth   = width;
      dmScreenSettings.dmPelsHeight   = height;
      dmScreenSettings.dmBitsPerPel   = bits;
      dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
      dmScreenSettings.dmDisplayFrequency=70;

// Essaye de faire les changements de rezo.  NOTE: CDS_FULLSCREEN permet d'enlever la bar demarrer
      if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
      {
   // Si ce n'est pas reussi, on donne le choix d'essayer en fenetre
         if (MessageBox(fenetre::hWnd,"Le mode plein ecran n'est pas suporté...\n essayer en mode fenetré?","Initialisation",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
         {
            fullscreen=FALSE;      // Fenetre choisi.  Fullscreen = FALSE
         }
         else
         {
      // Erreur, le programme ferme :
            MessageBox(fenetre::hWnd,"Erreur d'initialisation...","ERREUR",MB_OK|MB_ICONSTOP);
            return FALSE;
         }
      }
   }

   if (fullscreen)// Si on est en plein ecran
   {
//alors on a un style de fenêtre particulier
      dwExStyle=WS_EX_APPWINDOW;
      dwStyle=WS_POPUP;
      ShowCursor(FALSE);
   }
   else
   {
//sinon, on a un style de fenêtre normal :
      dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
      dwStyle=WS_OVERLAPPEDWINDOW;
   }
//on récupère les dimensions de la fenetre :
   AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);

   // Cree la fenetre
   if (!(hWnd=CreateWindowEx(dwExStyle,
            "OpenGL",// Nom de la class
            title,// Nom de la fenetre
            dwStyle |// Style de la fenetre
            WS_CLIPSIBLINGS |
            WS_CLIPCHILDREN,
            0, 0,// Position de la fenetre
            WindowRect.right-WindowRect.left,// Calcule la largeur
            WindowRect.bottom-WindowRect.top,// Calcule la hauteur
            NULL,
            NULL,
            hInstance,// Instance
            NULL)))
   {
//problème, donc on :
      FinGL();// supprime le contexte
      MessageBox(fenetre::hWnd,"Creation de la fenetre echoué.","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   static   PIXELFORMATDESCRIPTOR pfd=   
   {
      sizeof(PIXELFORMATDESCRIPTOR),// Taille du descripteur de fenetre
      1,// Numero de version
      PFD_DRAW_TO_WINDOW |// Le format sera pour une fenetre
      PFD_SUPPORT_OPENGL |// Le format sera pour Opengl
      PFD_DOUBLEBUFFER,// Le format sera en double buffering
      PFD_TYPE_RGBA,// Le format sera en RGBA
      bits,// Profondeur de couleur (32 ici)
      0, 0, 0, 0, 0, 0,
      0,
      0,
      0,
      0, 0, 0, 0,
      16,   // Z-Buffer
      0,// Pas de Stencil Buffer
      0,// Pas de buffer auxilliere
      PFD_MAIN_PLANE,   
      0,
      0, 0, 0   
   };
   
   if (!(hDC=GetDC(hWnd)))// A t on un DC
   {
//erreur, donc on quitte :
      FinGL();// supprime le contexte
      MessageBox(fenetre::hWnd,"Ne peut pas creer de support OpenGL ...","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd)))
   {
//si on ne trouve pas de format de pixel utilisable
      FinGL();// supprime le contexte
      MessageBox(fenetre::hWnd,"Ne trouve pas de format de pixel utilisable ...","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   if(!SetPixelFormat(hDC,PixelFormat,&pfd))
   {
      FinGL();// supprime le contexte
      MessageBox(fenetre::hWnd,"Ne peut pas utiliser le format de pixel ...","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   if (!(hRC=wglCreateContext(hDC)))
   {
      FinGL();// supprime le contexte
      MessageBox(fenetre::hWnd,"Ne peut pas cree de context d'affichage ...","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   if(!wglMakeCurrent(hDC,hRC))
   {
      FinGL();// supprime le contexte
      MessageBox(fenetre::hWnd,"Ne peut pas activer le context d'affichage ...","ERREUR",MB_OK|MB_ICONEXCLAMATION);
      return FALSE;
   }

   ShowWindow(hWnd,SW_SHOW);// affiche la fenetre
   SetForegroundWindow(hWnd);// Met en priorité superieure
   SetFocus(hWnd);   // Redirige le clavier vers la fenetre
   return TRUE;// Success
}

Une fois la fenetre faite, il faut traiter les messages qui lui arrivent... C'est ici que nous avons besoin de MainProc ! Un petit exemple de MainProc qui enregistre toutes les touches pressées dans un tableau ainsi que les mouvements de la souris :
Code: Tout sélectionner
LRESULT CALLBACK fenetre::WndProc(   HWND   hWnd,
                     UINT   uMsg,
                     WPARAM   wParam,
                     LPARAM   lParam)
{
   switch (uMsg)// Dispatche les messages de windows
   {
      case WM_KEYDOWN:// Une touche est pressée?
      {
         keys[wParam] = true;// Si oui, on la marque à vrai
         return 0;
      }

      case WM_KEYUP:// Une touche est relachée?
      {
         keys[wParam] = false;// Si oui, on la marque à faux
         return 0;
      }

      case WM_ACTIVATE:// Une activation de la fenetre?
      {
         if (!HIWORD(wParam))// Regarde si c'est une activation
         {
            active=true;
         }
         else
         {
            active=false;// Ou une desactivation
         }

         return 0;
      }

      case WM_COMMAND:// Intercepte les messages que j'ai defini
      {
      };

      case WM_SYSCOMMAND:// Intercepte les messages systemes
      {
         switch (wParam)
         {
            case SC_SCREENSAVE:// Economiseur d'ecran se declanche?
            case SC_MONITORPOWER:// Economie d'energie se declanche?
            return true;// Empeche d'arriver
         }
         break;
      }

      case WM_CLOSE:// Doit on fermet la fenetre?
      {
         PostQuitMessage(0);// Quitte l'appli
         return 0;
      }

      case WM_SIZE:// Redimension de la fenetre?
      {
         Redimension(LOWORD(lParam),HIWORD(lParam));
         return 0;
      }
        case WM_LBUTTONDOWN://souris droite enfoncé
        {
         keys[259] = true;// Si oui, on la marque à vrai
         return 0;
        }
        break;

        case WM_LBUTTONUP://souris droite relachée
        {
         keys[259] = false;// Si oui, on la marque à vrai
         return 0;
        }

        case WM_MBUTTONDOWN://souris milieu enfoncé
        {
         keys[258] = true;// Si oui, on la marque à vrai
         return 0;
        }
        break;

        case WM_MBUTTONUP://souris milieu relachée
        {
         keys[258] = false;// Si oui, on la marque à vrai
         return 0;
        }
        break;

        case WM_RBUTTONDOWN://souris droite enfoncé
        {
         keys[257] = true;// Si oui, on la marque à vrai
         return 0;
        }
        break;

        case WM_RBUTTONUP://souris droite relachée
        {
         keys[257] = false;// Si oui, on la marque à faux
         return 0;
        }
        break;

        case WM_MOUSEMOVE:
        {
            sourisx = LOWORD (lParam);
            sourisy = HIWORD (lParam);

         sourisdx=ancSourisx-sourisx;
         sourisdy=ancSourisy-sourisy;

            ancSourisx = sourisx;
            ancSourisy = sourisy;
         return 0;
        }
        break;

   }

   // Passe les autres messages à DefWindowProc
   return DefWindowProc(hWnd,uMsg,wParam,lParam);
}


Bon, avec ce début, vous ne pouvez pas encore faire grand chose (juste prendre un tube d'aspirine), inspirez vous pour la suite du TP de N4th (TP sur les pointeurs), ou du site suivant : http://neogamedev.chable.net/?PageID=2000
Tibo
Administrateur du site
 
Messages: 147
Inscription: 26 Mar 2008, 13:58


Retourner vers Programmation Windows

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité

cron
Hit-Parade des sites francophones