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 :

[openGL] heightmap: vbo + texturing


Sujet :

OpenGL

  1. #1
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Par défaut [openGL] heightmap: vbo + texturing
    Bonjours à tous,

    Je suis actuellement en train de me former à openGL et essaye de créer une carte en utilisant un heightmap, mon gestionnaire de fenêtre est SFML2 qui me permet aussi de charger les images (heightmap + textures)

    malheureusement, je coince un peu sur l'utilisation des vbo, ou plutot de texturer les terrain qui est stocké dans un vbo.

    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct Vertex
    {
        GLfloat x, y, z;        // position
        GLfloat nx, ny, nz;     // normale
        GLfloat s, t;           // texCoord
        GLubyte r, g, b;        // couleur
        GLubyte padding[29];    // alignement sur 32 bits (http://www.opengl.org/wiki/VBO)
    };
    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
    void Terrain::setVBO()
    {
        m_vbo = new Vertex[ m_height * m_width ];
        if( !m_vbo )
        {
            cerr << "Allocation de m_vbo impossible";
            exit(1);
        }
     
        uint index = 0;
        for(uint i=0; i<m_width; i++)
        {
            for(uint j=0; j<m_height; j++)
            {
                m_vbo[index].x = (GLfloat) i * m_pas_x;
                m_vbo[index].y = (GLfloat) m_heightmap.GetPixel(i, j).r * m_pas_y;
                m_vbo[index].z = (GLfloat) j * m_pas_z;
     
                m_vbo[index].r = m_heightmap.GetPixel(i, j).r;
                m_vbo[index].g = m_heightmap.GetPixel(i, j).r;
                m_vbo[index].b = m_heightmap.GetPixel(i, j).r;
     
                m_vbo[index].s = ((GLfloat) i)/m_width; 
                m_vbo[index].t = ((GLfloat) j)/m_height;
     
                index++;
            }
        }
     
        glGenBuffers(1, &m_id_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, m_id_vbo);
        glBufferData(GL_ARRAY_BUFFER, m_width*m_height*sizeof(Vertex), m_vbo, GL_STATIC_DRAW);
     
        /***************************************/
    //    m_texture = new sf::Image(); 
    //    m_texture->LoadFromFile("textures/Text_main.gif");
    //
    //    GLuint m_id_tex;
    //    glGenTextures(1, &m_id_tex);
    //    glBindTexture(GL_TEXTURE_2D, m_id_tex);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    //    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    //    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texture->GetWidth(), m_texture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture->GetPixelsPtr());
     
        /***************************************/
     
        // le tableau est chargé dans la RAM du GPU, on en a plus besoin
        delete[] m_vbo; m_vbo = NULL;
    }
    j'ai mis en commentaire ce que j'ai tenté de faire et qui ne fonctionne pas

    et voici le code d'affichage:
    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
    void Terrain::draw() const
    {
        glBindBuffer(GL_ARRAY_BUFFER, m_id_vbo);
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));
        glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(Vertex), BUFFER_OFFSET(32)); // les couleurs sont au 32ieme byte de la structure Vertex
    //    glTexCoordPointer( 2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(24)); // les coordonnées de texture sont au 32ieme byte de la structure Vertex
     
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_COLOR_ARRAY );
    //    glEnableClientState( GL_TEXTURE_COORD_ARRAY );
     
        glDrawElements(m_modeDessin, 6*(m_height-1)*(m_width-1), GL_UNSIGNED_INT, BUFFER_OFFSET(0));
     
    //    glDisableClientState( GL_TEXTURE_COORD_ARRAY );
        glDisableClientState( GL_COLOR_ARRAY );
        glDisableClientState( GL_VERTEX_ARRAY );
    }
    Malgré mes différents tests, je n'arrive pas à texturer ma map :-(
    J'en appel donc à votre aide pour m'expliquer comment faire ou me donner un lien. Merci d'avance.

    ps: si mon code est buggé ou mauvais, j'aimerais tous les conseils dessus

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 173
    Billets dans le blog
    155
    Par défaut
    Bonjour,

    Je me demande quelle est la conséquence du problème (artefacts graphiques ?).
    Sinon, je me demande ce qu'il y a dans BUFFER_OFFSET, mais je pense qu'il ne faut pas l'utiliser comme cela, mais plus en passante 32+24.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Par défaut
    Le problème c'est que ça ne fonctionne pas du tout, je ne voit pas comment procéder, autant quand j'utilisai glVertex3f et glTexCoord2f j'ai réussi sans difficulté à texturer ma map (je précise qu'il s'agit d'une seule texture pour tout la carte, je verrais plus tard pour faire du texturing en fonction de la hauteur)
    Mais depuis que je l'ai passé en vbo, je bloque.

    Dans le bout de code que j'ai fourni plus haut, j'ai chargé l'image via SFML, transformée en texture openGL via glGenTextures, glBindTexture, glTexParameteri et glTexImage2D. J'ai également rentré les coordonnées de chaque vertex de la map dans la texture avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     m_vbo[index].s = ((GLfloat) i)/m_width; 
     m_vbo[index].t = ((GLfloat) j)/m_height;
    Puis j'utilise glTexCoordPointer mais en vain.
    Déjà je me demande comment indiquer que c'est la texture chargée précédemment qu'il doit utiliser.

    pour le BUFFER_OFFSET(), il s'agit d'une macro, la voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #define BUFFER_OFFSET(a) ((char*)NULL + (a))
    qui permet de donner l'adresse du a-ième élément dans la structure Vertex.

  4. #4
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 173
    Billets dans le blog
    155
    Par défaut
    Pour spécifier une texture, soit vous passer par un uniforme (technique avec les shaders) soit vous spécifier la texture avec glBindTexture().

    Pour le BUFFER_OFFSET(), pour spécifier les coordonnées de texture, il faut bien mettre 24, je mettais trompé la première fois. Sinon, pour le reste, le code me semblait bon. Avez vous vérifier les erreurs avec glGetError() ?
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  5. #5
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2004
    Messages
    66
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2004
    Messages : 66
    Par défaut
    j'ai ajouté glBindTexture avec l'id de la texture juste avant le glTexCoordPointer mais ca ne fonctionne toujours pas, voici mon nouveau code:

    remplissage du VBO :
    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
    void Terrain::setVBO()
    {
        m_vbo = new Vertex[ m_height * m_width ];
        if( !m_vbo )
        {
            std::cerr << "Allocation de m_vbo impossible";
            exit(1);
        }
     
        uint index = 0;
        for(uint i=0; i<m_width; i++)
        {
            for(uint j=0; j<m_height; j++)
            {
                m_vbo[index].x = (GLfloat) i * m_pas_x;
                m_vbo[index].y = (GLfloat) m_heightmap.GetPixel(i, j).r * m_pas_y;
                m_vbo[index].z = (GLfloat) j * m_pas_z;
     
                m_vbo[index].r = m_heightmap.GetPixel(i, j).r;
                m_vbo[index].g = m_heightmap.GetPixel(i, j).r;
                m_vbo[index].b = m_heightmap.GetPixel(i, j).r;
     
                m_vbo[index].s = ((GLfloat) i)/m_width;
                m_vbo[index].t = ((GLfloat) j)/m_height;
     
                index++;
            }
        }
     
        glGenBuffers(1, &m_id_vbo);
        glBindBuffer(GL_ARRAY_BUFFER, m_id_vbo);
        glBufferData(GL_ARRAY_BUFFER, m_width*m_height*sizeof(Vertex), m_vbo, GL_STATIC_DRAW);
     
        // le tableau est chargé dans la RAM du GPU, on en a plus besoin
        delete[] m_vbo; m_vbo = nullptr;
    }
    Chargement de la texture :
    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
    void Terrain::chargerTexture()
    {
        m_texture = new sf::Image();
        if( !m_texture )
        {
            std::cerr << "Allocation de m_texture impossible";
            exit(1);
        }
        m_texture->LoadFromFile( m_srcTexture );
     
        glGenTextures(1, &m_id_tex);
        glBindTexture(GL_TEXTURE_2D, m_id_tex);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texture->GetWidth(), m_texture->GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, m_texture->GetPixelsPtr());
     
        /* Texture en mémoire, on en a plus besoin */
        delete m_texture; m_texture = nullptr;
    }
    Affichage du terrain :
    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
    void Terrain::draw() const
    {
        glBindBuffer(GL_ARRAY_BUFFER, m_id_vbo);
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(0));
        glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(Vertex), BUFFER_OFFSET(32)); // les couleurs sont au 32ieme byte de la structure Vertex
     
        glBindTexture(GL_TEXTURE_2D, m_id_tex);
        glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), BUFFER_OFFSET(24)); // les coordonnées de texture sont au 32ieme byte de la structure Vertex
     
        glEnableClientState( GL_VERTEX_ARRAY );
        glEnableClientState( GL_COLOR_ARRAY );
        glEnableClientState( GL_TEXTURE_COORD_ARRAY );
     
        glDrawElements(m_modeDessin, 6*(m_height-1)*(m_width-1), GL_UNSIGNED_INT, BUFFER_OFFSET(0));
     
        glDisableClientState( GL_TEXTURE_COORD_ARRAY );
        glDisableClientState( GL_COLOR_ARRAY );
        glDisableClientState( GL_VERTEX_ARRAY );
    }
    J'ai oublié de préciser que j'utilise un tableau d'index pour afficher le terrain d'ou le 6*(m_height-1)*(m_width-1) pour le nombre d'elements.

    Tout fonctionne correctement, sauf le texturing.

Discussions similaires

  1. Réponses: 10
    Dernier message: 08/06/2009, 12h30
  2. SDL/OpenGL extentions VBO
    Par nightwar dans le forum SDL
    Réponses: 5
    Dernier message: 01/01/2009, 18h31
  3. Java openGL: Load une Texture ?
    Par rere56 dans le forum Interfaces Graphiques en Java
    Réponses: 1
    Dernier message: 25/06/2007, 18h28
  4. Problème VBO + texture
    Par f56bre dans le forum OpenGL
    Réponses: 2
    Dernier message: 18/08/2006, 10h20
  5. [OpenGL] Récupperer une texture
    Par WarDrone dans le forum OpenGL
    Réponses: 2
    Dernier message: 16/06/2006, 10h42

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