IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

OpenGL Discussion :

[Debutant] Un thread qui dessine sur une fenetre ???


Sujet :

OpenGL

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 180
    Points : 90
    Points
    90
    Par défaut [Debutant] Un thread qui dessine sur une fenetre ???
    Bonjour à tous,

    Je suis en train (d'essayer) de faire un petit jeu vidéo du genre de Pong avec OpenGL. Mon "support" de dessin est une fenetre Windows (j'utilise l'ApiWin32, je programme en c++). J'aimerais que toute les fonctions "d'initialisation" (GetDC(); SetPixelFormat(); wglCreateContext(); wglMakeCurrent ()...) soient dans la procédure de la fenetre Windows mais en revanche, j'aimerais que le dessin sur la fenetre soit géré par un thread indépendant. Malheureusement, je rencontre quelques problèmes. En effet, lorsque je lance mon programme, rien ne s'affiche ou alors une image avec un mélange de tout ce qu'il y'a à l'écran clignote). Je ne comprends vraiment pas d'où vient ce problème!!!

    Voici mon code

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
     
    //La procédure de fenetre
     
    static LRESULT CALLBACK procFenetreJeu(HWND fenetre, UINT message, WPARAM wParam, LPARAM lParam)
    {
        static HANDLE threadJeu;
        static DWORD idThreadJeu;
     
        static HDC hdc;
        static HGLRC hrc;
     
        static PIXELFORMATDESCRIPTOR pfd = {sizeof (PIXELFORMATDESCRIPTOR),1,
        PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER,
        16,0, 0, 0, 0, 0, 0, 0, 0,	0, 0, 0, 0, 0,16,0, 0, 0, 0, 0, 0, 0};
     
        switch(message)
        {
            case WM_CREATE:
                SetWindowLong(fenetre,GWL_STYLE,WS_CAPTION|WS_SYSMENU|WS_SIZEBOX);
                ShowWindow(fenetre,SW_SHOWMAXIMIZED);
     
                hdc = GetDC ( fenetre );
                SetPixelFormat (hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
                hrc = wglCreateContext (hdc);
                wglMakeCurrent (hdc, hrc);
     
                threadJeu = CreateThread(NULL,0,&PONG_thread_principal,(LPVOID)hdc,0,&idThreadJeu);
            break;
     
            case WM_SIZE:
                SuspendThread(threadJeu);
                glViewport (0,0,LOWORD (lParam),HIWORD (lParam));
                glMatrixMode (GL_PROJECTION);
                glLoadIdentity ();
                gluPerspective (45,(float)(LOWORD(lParam))/(float)(HIWORD(lParam)),1,100);
                ResumeThread(threadJeu);
            break;
     
            case WM_DESTROY:
                CloseHandle(threadJeu);
     
                wglMakeCurrent (NULL, NULL);
                wglDeleteContext (hrc);
                ReleaseDC (fenetre,hdc);
     
                PostQuitMessage(0);
            break;
     
            default:
                return DefWindowProc(fenetre,message,wParam,lParam);
        }
     
        return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
    //Le thread de dessin
     
    DWORD WINAPI PONG_thread_principal(LPVOID lpParams)
    {
        HDC hdc = (HDC)lpParams;
     
        while(1)
        {
            glClear (GL_COLOR_BUFFER_BIT);
            glMatrixMode (GL_MODELVIEW);
            glLoadIdentity ();
     
                /************************** DESSIN ********************************/
     
                gluLookAt (7,7,-10,0,0,0,0,1,0);
     
                glBegin (GL_QUADS);
                    glColor3d(1,0,0);
                        glVertex3i (-1,-1,1);
                        glVertex3i (-1,1,1);
                        glVertex3i (1,1,1);
                        glVertex3i (1,-1,1);
                    glColor3d(0,0,1);
                        glVertex3i (-1,-1,-1);
                        glVertex3i (-1,1,-1);
                        glVertex3i (1,1,-1);
                        glVertex3i (1,-1,-1);
                    glColor3d(0,1,0);
                        glVertex3i (-1,1,-1);
                        glVertex3i (1,1,-1);
                        glVertex3i (1,1,1);
                        glVertex3i (-1,1,1);
                    glColor3d(1,1,0);
                        glVertex3i (-1,-1,-1);
                        glVertex3i (1,-1,-1);
                        glVertex3i (1,-1,1);
                        glVertex3i (-1,-1,1);
                    glColor3d(0,1,1);
                        glVertex3i (-1,-1,-1);
                        glVertex3i (-1,-1,1);
                        glVertex3i (-1,1,1);
                        glVertex3i (-1,1,-1);
                    glColor3d(1,0,1);
                        glVertex3i (1,-1,-1);
                        glVertex3i (1,-1,1);
                        glVertex3i (1,1,1);
                        glVertex3i (1,1,-1);
                    glEnd();
     
                /******************************************************************/
     
                SwapBuffers (hdc);
            Sleep(50);
        }
     
        return 0;
    }
    Un GRAND merci d'avance de votre aide!!

    Bonne soirée.

    Spartan03
    Pourquoi faire simple quand on peut faire compliqué!

  2. #2
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    il est extrèmement risqué de lancer des commandes opengl dans 2 threads différents pouvant s'exécuter en simultané
    le résultat n'est pas garanti

    je ne sais plus où j'ai lu cela, dans le redbook ou le bluebook ou quelque part sur le site officiel opengl

    je te conseille de te limiter aux threads pour gérer par exemple la physique ou les déplacement, tout ce qui ne demande pas d'appel aux méthodes opengl donc
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 180
    Points : 90
    Points
    90
    Par défaut
    Ok, si j'ai bien compris, il faut que je mette toute les procédures liées au dessin dans un autre thread. Et pour ce qui est des messages récupérés (boutons, souris) il faut que ma fenetre les renvoie au thread.
    Pour ce qui est de mon programme, je voulais justement que tout soit basé sur un systèmee multithread (un thread pour chacune des raquettes, un thread pour la balle). Je ne pense pas qu'il y'ait des bug au niveau du moteur physique (si on peut appeler ça comme ça) car a part les collisions balle->raquette et balle->mur il n'y a pas grand chose.

    Merci bien!
    Pourquoi faire simple quand on peut faire compliqué!

  4. #4
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    Citation Envoyé par Spartan03
    Ok, si j'ai bien compris, il faut que je mette toute les procédures liées au dessin dans un autre thread. Et pour ce qui est des messages récupérés (boutons, souris) il faut que ma fenetre les renvoie au thread.
    Je dirai qu'à partir du moment où tous tes appels à opengl (glFunc ou gluFunc) sont dans le même thread, ton problème d'affichage devrait se résoudre

    Pour ce qui est de mon programme, je voulais justement que tout soit basé sur un systèmee multithread (un thread pour chacune des raquettes, un thread pour la balle). Je ne pense pas qu'il y'ait des bug au niveau du moteur physique (si on peut appeler ça comme ça) car a part les collisions balle->raquette et balle->mur il n'y a pas grand chose.

    Merci bien!
    De ce côté là pas de problème
    par contre, veilles bien à ce qu'aucun thread ne modifie les données que tu utilises dans un autre en particulier dans ton thread d'affichage
    je te conseillerai plutot de ne pas faire de thread pour ton affichage et de lancer des threads pour tes calculs et d'attendre que tous les threads soient terminés pour effectuer ton affichage

    si tu veux la bibliothèque glfw est livrée avec des exemples dont un de particules en multithreading
    glfw.sourceforge.net
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  5. #5
    Rédacteur
    Avatar de bafman
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    2 574
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Novembre 2003
    Messages : 2 574
    Points : 5 323
    Points
    5 323
    Par défaut
    le probleme vient probablement qu'avec 2 thread different, c'est qu'avant chaque appel openGL, il fautdrait faire de wglSetCurrentDC ou autre fonction lié au system de fenetrage pour lui dire sur quel context il fonctionne...
    * Il est infiniment plus simple de faire rapidement un code qui marche que de faire un code rapide qui marche
    * pour faciliter les recherches, n'oubliez pas de voter pour les réponses pertinentes
    Mes articles

  6. #6
    Expert confirmé
    Avatar de shenron666
    Homme Profil pro
    avancé
    Inscrit en
    Avril 2005
    Messages
    2 524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : avancé

    Informations forums :
    Inscription : Avril 2005
    Messages : 2 524
    Points : 5 184
    Points
    5 184
    Par défaut
    bien vu bafman, il faudrait tester
    mais d'un autre côté ça limite l'intérêt du multithreading, il ne faudrait pas laisser 2 threads faisant appel à des commandes gl s'executer en même temps
    ce serai un bon sujet à développer pour y faire référence dans la FAQ vous le pensez pas ?
    Tutoriels OpenGL
    Je ne répondrai à aucune question en MP
    - Si c'est simple tu dis que c'est compliqué et tu le fait
    - Si c'est compliqué tu dis que c'est simple et tu le sous-traite ou le fait faire par un stagiaire.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    180
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 180
    Points : 90
    Points
    90
    Par défaut Une solution
    Au cas où ça intéresserait quelqu'un, je vous donne la méthode que j'utilise (en programmant en Windows mais avec SDL ou même d'autres librairies il devrait y avoir des fonctions similaires
    Lors de la création de la fenetre (message WM_CREATE), ou d'un autre "support" (SDL, Glut...) je récupère un DC sur ce support (GetDC(fenetre)) et je lance le thread en lui passant le DC en parametre.

    La je lie mon DC avec le RC et je lance la boucle de jeu.
    A chaque itération, je récupère les messages divers envoyés au Thread. L'un de ces message (je l'ai appelé TM_RESIZE) contient les fonctions de "recadrement" (glViewport ();glMatrixMode();glLoadIdentity ();gluPerspective (45,(float)(LOWORD(message.lParam))/(float)(HIWORD(message.lParam)),1,100).
    En dessous je gère l'affichage.
    Lorsque le thread prend fin (on sort de la boucle), je délie le HDC et le RC puis je ferme le programme (PostQuitMessage(0))!

    Au niveau des jeux vidéos, je me suis beaucoup inspiré du fonctionnement de Windows (merci Bill Gates) :
    Je crée un objet (par exemple RAQUETTE pour un PONG). Cet objet contient les infos de positionnement et des méthodes (je programme en c++, en c il faudra créer des fonctions externes à la classe, enfin à la struct).

    Lorsqu'on crée l'objet, un thread se lance, c'est ce thread qui gèrera tout l'objet, son cerveau en quelque sorte.
    Une fois lancé, le thread initialise la raquette puis attend la réception d'une message de la part du thread comme quoi il peut lancer la boucle principale (IA, récéption des messages).
    Dès que ce message (RM_GO par exemple) est reçu, on lance le thread.
    Ce thread gère uniquement la position de l'objet et éventuellement, il la modifie lui même dans le cas où l'IA de la raquette est activée. Par exemple, le message RM_DEPLACEMENT wParam = x ;lParam = y mettra le coin supérieur gauche (et le reste suit) de la raquette sur le point de coordonnées (x;y).

    L'objet doit aussi contenir une fonction membre dessiner() qui contient les fonctions de desin de la raquette et qu'on exécutera au moment voulu.

    Bien sûr ceci n'était qu'un exemple et le création de thread n'est pas obligatoire (et même déconseillée) dans le cas où vous n'utlisez pas d'IA pour vos objets.

    Vous pouvez ainsi vous contenter d'une procédure style Windows ou même de fonctions (membres ou pas).

    Tout dépend de votre imagination et votre créativité !

    Voilà, en espérant vous avoir donné quelques idées!

    Spartan03
    Pourquoi faire simple quand on peut faire compliqué!

Discussions similaires

  1. Réponses: 1
    Dernier message: 05/03/2009, 15h21
  2. [debutant]dessins dans une fenetre
    Par drosophile dans le forum 2D
    Réponses: 4
    Dernier message: 04/11/2004, 14h55
  3. [Servlet] [Image] Dessiner sur une image
    Par gaia_dev dans le forum 2D
    Réponses: 5
    Dernier message: 01/09/2004, 17h11
  4. application qui connecte sur une page web
    Par spoolz dans le forum Entrée/Sortie
    Réponses: 6
    Dernier message: 14/04/2004, 09h47
  5. Aide sur une fenetre
    Par Ray-j dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 29/11/2002, 08h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo