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

GTK+ avec C & C++ Discussion :

GtkGLExtmm : usage de « create_gl_context() »


Sujet :

GTK+ avec C & C++

  1. #1
    Membre éclairé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 190
    Par défaut GtkGLExtmm : usage de « create_gl_context() »
    Salut à tous !

    J’avance doucement dans la conversion des tutoriels de NeHe vers GtkGLExtmm. On peut trouver tous ce qu’il faut pour s’en sortir sur Internet, mais c’est tout de même épars et on risque régulièrement de faire fausse route. Du coup, je pense proposer aux responsables de la page de Developez.com des tutoriels de NeHe de stocker mes codes, cela fera un exemple pour ceux qui voudraient se lancer dans l’aventure. Autant que le temps que je passe à m’en sortir serve à d’autres.

    Pour l’instant, je me pose des questions sur la bonne utilisation de la fonction « create_gl_context() ». Dans la mesure où je cherche à faire en sorte que le code n’en fasse pas plus que nécessaire, je ne l’utilise que dans le contrôleur de l’évènement « realize », c’est-à-dire, si j’ai bien tout compris, à l’initialisation de la fenêtre. Dans mes sources, il s’agit de la procédure « on_realize_event », dont la définition se trouve dans le fichier « src/fenetre.hpp » et l’implémentation dans le fichier « src/fenetre.cpp ».

    Le code fonctionne sans problème, mais je voudrais m’assurer que je ne fais pas fausse route, dans la mesure où le tutoriel officiel, par exemple dans l’horloge basée sur Cairo, appelle « create_cairo_context() » dans le contrôleur de l’évènement « expose ». Cela dit, je soupçonne le tutoriel de faire ainsi pour limiter le nombre de lignes de codes (il n’est alors pas besoin de contrôleur pour l’évènement « realize »).

    Donc, est-il possible de confirmer que l’on peut appeler la fonction « create_gl_context() » une seule fois et ensuite utiliser ce contexte à chaque fois qu’il en est besoin ?

    Je gère le code à l’aide de CMake, je fournis ici fichier « CMakelists.txt » associé, qui est situé dans le répertoire racine du projet. Toutes les sources du code sont tous regroupés dans un sous-répertoire nommé « src ».

    Fichier « CMakeLists.txt » :

    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
    ## Génération des tutoriels OpenGL de NeHe version OpenGL.
     
    cmake_minimum_required(VERSION 2.6)
     
    project(Tutoriel1 CXX)
     
    # Répertoire où placer l’exécutable.
    set(EXECUTABLE_OUTPUT_PATH bin/${CMAKE_BUILD_TYPE})
    # Nom de l’exécutable.
    set(EXECUTABLE_NAME tutoriel1)
     
    find_package(PkgConfig)
     
    pkg_check_modules(Glibmm glibmm-2.4>=2.4.0)
    pkg_check_modules(GTKmm gtkmm-2.4>=2.4.0)
    pkg_check_modules(GLExtmm gtkglextmm-1.2>=1.2.0)
    link_directories(
            ${Glibmm_LIBRARY_DIRS}
            ${GTKmm_LIBRARY_DIRS}
            ${GLExtmm_LIBRARY_DIRS}
    )
    include_directories(
            ${Glibmm_INCLUDE_DIRS}
            ${GTKmm_INCLUDE_DIRS}
            ${GLExtmm_INCLUDE_DIRS}
    )
     
    file(
            GLOB_RECURSE
            source_files
            src/*
    )
     
    add_executable(
            ${EXECUTABLE_NAME}
            ${source_files}
    )
     
    target_link_libraries(
            ${EXECUTABLE_NAME}
            ${Glibmm_LIBRARIES}
            ${GTKmm_LIBRARIES}
            ${GLExtmm_LIBRARIES}
    )
    Fichier « src/erreurs.hpp » :

    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #ifndef ERREURS_HPP
    #define ERREURS_HPP
     
    /*
     * Exceptions pour la gestions des erreurs.
     */
     
    #include <exception>
    #include <sstream>
     
    /* Espace de nommage pour la gestion des erreurs. */
    namespace Erreurs {
    /* -- Erreurs provoquées par l’interface graphique. ---------------------- */
      class ErreurInterface: public std::exception {
        public:
          /* Constructeur par défaut. */
          ErreurInterface () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurInterface () throw () {}
     
          /* Génére le message d’erreur. */
          virtual const char* what () const throw () {
            /* Le message d’erreur. */
            std::stringstream message;
            message << "une erreur s’est produite dans l’interface graphique.";
            return message.str().c_str();
          }
      };
     
    /* -- Erreurs lors de la création du contexte OpenGL. -------------------- */
      class ErreurCreationContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurCreationContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurCreationContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            /* Le message d’erreur. */
            std::stringstream message;
            message << "impossible de créer un contexte OpenGL.";
            return message.str().c_str();
          }
      };
     
    /* -- Erreurs à l’obtention du contexte OpenGL. -------------------------- */
      class ErreurObtentionContexte: public ErreurInterface {
        public:
          /* Constructeur par défaut. */
          ErreurObtentionContexte () throw () {}
     
          /* Destructeur. */
          virtual ~ErreurObtentionContexte () throw () {}
     
          /* Génère le message d’erreur. */
          virtual const char* what () const throw () {
            /* Le message d’erreur. */
            std::stringstream message;
            message << "impossible d’obtenir le contexte OpenGL.";
            return message.str().c_str();
          }
      };
    }
     
    #endif  // #ifndef ERREURS_HPP
    Fichier « src/fenetre.hpp » :

    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
    #ifndef FENETRE_HPP
    #define FENETRE_HPP
     
    /*
     * Définitions des classes gérants le fenêtrage OpenGL.
     */
     
    #include <gtkmm/window.h>
    #include <gtkmm/drawingarea.h>
    #include <gtkglmm.h>
     
    #include "erreurs.hpp"
     
    /* Espace de nommage pour la gestion de l’interface. */
    namespace Interface {
      /* Classe pour la zone de rendu OpenGL. */
      class GlDrawingArea: public Gtk::DrawingArea,
                           public Gtk::GL::Widget<GlDrawingArea> {
        private:
          /* Indique si on se trouve en mode plein écran. */
          bool pleinEcran;
     
        public:
          GlDrawingArea ();
          virtual ~GlDrawingArea ();
     
        protected:
          /* -- Controlleurs: */
     
          /* À l’initialisation de la fenêtre. */
          virtual void on_realize ();
     
          /* À la demande d’affichage. */
          virtual bool on_expose_event (GdkEventExpose* event);
     
          /* Au changement de taille de la fenêtre. */
          virtual bool on_configure_event (GdkEventConfigure* event);
      };
     
    /* ----------------------------------------------------------------------- */
     
      /* Classe pour la fenetre principale. */
      class Fenetre: public Gtk::Window {
        public:
          Fenetre ();
          virtual ~Fenetre();
     
        private:
          /* -- Composants membres : */
     
          /* Zone de rendu OpenGL. */
          GlDrawingArea zoneRendu;
      };
    }
     
    #endif  // #ifndef FENETRE_HPP
    Fichier « src/fenetre.cpp » :

    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    /*
     * Implémentations du fenêtrage OpenGL.
     */
     
    #include <glibmm/error.h>
    #include <cstdlib>
    #include <GL/gl.h>
    #include <GL/glu.h>
    #include <sstream>
     
    #include "fenetre.hpp"
     
    /* -- Constructeur par défaut de GlDrawingArea. -------------------------- */
    Interface::GlDrawingArea::GlDrawingArea (): Gtk::DrawingArea (),
                                                pleinEcran (true) {
      /* Configuration d’OpenGL */
      Glib::RefPtr<Gdk::GL::Config> configuration;
     
      /* Tente d’ouvrir une espace à double tampon. */
      configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA   |
                                              Gdk::GL::MODE_DEPTH  |
                                              Gdk::GL::MODE_DOUBLE);
      if (!configuration) {
        g_warning("Impossible de configurer OpenGL en mode double tampon, tente le mode simple tampon.\n");
        /* Tente de configurer un tampon simple. */
        configuration = Gdk::GL::Config::create(Gdk::GL::MODE_RGBA  |
                                                Gdk::GL::MODE_DEPTH);
        if (!configuration) {
          g_critical("Impossible de configurer OpenGL.\n");
          std::exit(-2);
        }
      }
     
      /* Donne accès à OpenGL au composant. */
      set_gl_capability(configuration);
    }
     
    /* -- Destructeur de GlDrawingArea. -------------------------------------- */
    Interface::GlDrawingArea::~GlDrawingArea () {
    }
     
    /* -- Initialisation du contexte OpenGL. --------------------------------- */
    void Interface::GlDrawingArea::on_realize () {
      Gtk::Widget::on_realize();
     
      if (!create_gl_context()) throw Erreurs::ErreurCreationContexte ();
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl) throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
      /* Permet un joli ombrage. */
      glShadeModel(GL_SMOOTH);
     
      /* Fond noir. */
      glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     
      /* Mis en place du tampon de profondeur. */
      glClearDepth(1.0f);
      /* Mis en place du test de profondeur. */
      glEnable(GL_DEPTH_TEST);
      /* Le type de test de profondeur . */
      glDepthFunc(GL_LEQUAL);
     
      /* Très jolis calculs de perspective. */
      glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
     
      fenetreGl->gl_end();
    }
     
    /* -- À la demande  d’affichage de GlDrawingArea. ------------------------ */
    bool Interface::GlDrawingArea::on_expose_event (GdkEventExpose* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
    //   glClear(GL_COLOR_BUFFER_BIT);
      /* Vide l'écran et le Z-Buffer (Depth Buffer : contient les informations
         de profondeur de chaque pixel). */
      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      /* Repositionne la caméra. */
      glLoadIdentity();
     
      /* Bouge de 1.5 unités vers la gauche et de 6.0 unités vers l'intérieur
         de l'écran. */
      glTranslatef(-1.5f,0.0f,-6.0f);
     
      /* Dessiner un Triangle. */
      glBegin(GL_TRIANGLES);
        /* Point du haut. */
        glVertex3f( 0.0f, 1.0f, 0.0f);
        /* Point en bas à gauche. */
        glVertex3f(-1.0f,-1.0f, 0.0f);
        /* Point en bas à droite */
        glVertex3f( 1.0f,-1.0f, 0.0f);
      /* Le dessin du Triangle est fini */
      glEnd();
     
      /* Bouge de 3.0f unités vers la droite. */
      glTranslatef(3.0f,0.0f,0.0f);
     
      /* Dessin d'un quadrilatère. */
      glBegin(GL_QUADS);
        /* Haut Gauche. */
        glVertex3f(-1.0f, 1.0f, 0.0f);
        /* Haut Droite. */
        glVertex3f( 1.0f, 1.0f, 0.0f);
        /* Bas Droite. */
        glVertex3f( 1.0f,-1.0f, 0.0f);
        /* Bas Gauche. */
        glVertex3f(-1.0f,-1.0f, 0.0f);
      glEnd();
     
      fenetreGl->gl_end();
      fenetreGl->swap_buffers();
     
      return Gtk::Widget::on_expose_event(event);
    }
     
    /* -- Lorsque la fenêtre est redimensionnée. ----------------------------- */
    bool Interface::GlDrawingArea::on_configure_event (GdkEventConfigure* event) {
      /* Fenêtre OpenGL. */
      Glib::RefPtr<Gdk::GL::Window> fenetreGl = get_gl_window();
      if (!fenetreGl)  throw Erreurs::ErreurObtentionContexte ();
     
      fenetreGl->gl_begin(get_gl_context());
     
      /* Choisir la matrice de projection. */
      glMatrixMode(GL_PROJECTION);
      /* Remettre a zéro de la matrice de projection. */
      glLoadIdentity();
     
      /* Calculer le ratio pour la perspective de la fenêtre. */
      gluPerspective(45.0f, static_cast<GLfloat>(get_width())
                              / static_cast<GLfloat>(get_height()),
                     0.1f,100.0f);
      /* Choisir la matrice de modélisation. */
      glMatrixMode(GL_MODELVIEW);
      /* Remetre à zéro la matrice de modélisation. */
      glLoadIdentity();
     
      fenetreGl->gl_end();
     
      return Gtk::Widget::on_configure_event(event);
    }
     
     
    /* -- Constructeur par défaut de la fenêtre. ----------------------------- */
    Interface::Fenetre::Fenetre (): Gtk::Window (), zoneRendu () {
      set_title("Tutoriel 1");
      set_default_size(640, 480);
      set_border_width(2);
     
      add(zoneRendu);
     
      show_all_children();
    }
     
    /* -- Destructeur de la fenêtre. ----------------------------------------- */
     
    Interface::Fenetre::~Fenetre () {
    }
    Fichier « src/main.cpp » :

    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
    59
    60
    61
    62
    63
    64
    65
    66
    /*
     * Premier tutoriel : création d’une fenêtre avec une zone OpenGL.
     */
     
    #include <iostream>
    #include <gtkmm/main.h>
    #include <gtkglmm.h>
    #include <sstream>
    #include <glibmm/error.h>
    #include <exception>
     
    #include "erreurs.hpp"
    #include "fenetre.hpp"
     
    /*
     * Principale fonction du programme.
     * Entrées :
     *   argc  Nombre d’arguments.
     *   argv  Valeures des arguments.
     * Retourne :
     *   0 si tout s’est bien passé.
     *   -1 en cas d’erreur venant de la GLib ou de ses dérivés.
     *   -2 en cas d’erreur en provenance d’OpenGL.
     *   -3 en cas d’erreur en provenance de la bibliothèque standard.
     *   -4 en cas d’erreur non standard.
     */
    int main (int argc, char** argv) {
      try {
        /* Boucle d’évènements. */
        const Gtk::Main kit(argc, argv);
        Gtk::GL::init(argc, argv);
     
        /* Fenêtre principale. */
        Interface::Fenetre principale;
     
        kit.run(principale);
     
        return 0;
      }
      catch(const Glib::Error &ex) {
        /* Message d’erreur. */
        std::ostringstream message;
        message << "Erreur venant de GLib : " <<  ex.what() << '\n';
        g_warning(message.str().c_str());
        return -1;
      }
      catch (const Erreurs::ErreurInterface &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur de contexte OpenGL : " << e.what() << '\n';
        g_critical(message.str().c_str());
        return -2;
      }
      catch (const std::exception &e) {
        /* Message d’erreur. */
        std::stringstream message;
        message << "Erreur venant de la bibliothèque standard : " << e.what()
                << '\n';
        g_critical(message.str().c_str());
        return -3;
      }
      catch (...) {
        g_critical("Exception non-standard.\n");
        return -4;
      }
    }
    Par ailleurs, si vous avez des remarques sur la façon de faire, n’hésitez pas : j’essaye de trouver les meilleures pratiques.

    À bientôt.

    Le Farfadet Spatial

  2. #2
    Membre éclairé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 190
    Par défaut
    Salut à tous !

    J’imagine que si personne n’a répondu, c’est que personne n’a d’idée précise. Toutefois, au cas où, j’essaye de relancer le sujet : est-ce que quelqu’un sait si je peux me permettre de lancer « create_gl_context() » une seule fois ou bien s’il faut l’exécuter à chaque fois que l’on fait une nouvelle opération dans le contexte OpenGL ?

    À bientôt.

    Le Farfadet Spatial

  3. #3
    Modérateur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2009
    Messages
    1 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 395
    Par défaut
    Bonjour, ta question n'a à mon avis pas trop de réponses parce qu'elle est plus orientée opengl que GTK. Essaie de voir s'il y a une section des forums developez plus adaptées à opengl. En ce qui concerne cairo, la création du contexte se fait en répons à l'événement expose-event parce que cario est stateless, c'est à dire qu'il ne conserve pas l'état graphique en cours, il faut donc à chaque fois recréer le contexte graphique.

  4. #4
    Membre éclairé
    Avatar de Le Farfadet Spatial
    Homme Profil pro
    En cours de précision…
    Inscrit en
    Avril 2008
    Messages
    190
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : En cours de précision…

    Informations forums :
    Inscription : Avril 2008
    Messages : 190
    Par défaut
    Salut à tous !

    Merci Liberforce pour cette réponse, qui m’apporte pas mal d’informations.

    Déjà, je n’avais pas réalisé que Cairo ne conservait pas son état, c’est bon à savoir. Si je ne m’abuse, OpenGL, au contraire, sauvegarde son état. Ce qui pourrait expliquer qu’il ne soit pas nécessaire de créer un contexte OpenGL qu’une seule fois.

    Cela dit, j’irais poser la question sur la partie OpenGL, mais plus tard : j’ai quelques problèmes à régler tout d’abord.

    À bientôt.

    Le Farfadet Spatial

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Quel usage faites vous de Python (2004 - 2008) ?
    Par Guigui_ dans le forum Général Python
    Réponses: 130
    Dernier message: 03/12/2008, 23h59
  2. [POI] Usage à partir d'une Servlet
    Par fredmorvant29 dans le forum Servlets/JSP
    Réponses: 8
    Dernier message: 19/07/2004, 15h35

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