Partage
  • Partager sur Facebook
  • Partager sur Twitter

[OpenGL, SDL]Blit de surface

toutes mes images sont blanches!

    18 novembre 2007 à 3:11:12

    Bon alors voilà, j'ai décidé d'utiliser OpenGL pour l'affichage de mes images plutôt que les fonctions de base de la SDL pour améliorer les performances. J'ai donc écrit une fonction de "blittage" de texture OpenGL sur l'écran pour faire mon jeu 2D.

    Jusque là, tout fonctionne parfaitement, et j'obtiens une fonction qui fait exactement ce que je veux. Fier de moi et voulant améliorer toujours plus, je crée donc une classe Image qui stockera toutes les informations nécessaires à ce "blit" et surtout me facilitant grandement le traitement de plusieurs images à le fois. Et là, c'est la cata...

    Voici le code:

    Fichier affichage.h
    1. #ifndef AFFICHAGE_H
    2. #define AFFICHAGE_H
    3. #include "define.h"
    4. #include "moteur.h"
    5. class Image {
    6.     private:
    7.     GLuint image;
    8.     int largeur;
    9.     int hauteur;
    10.     SDL_Surface* flipSurface(SDL_Surface*);
    11.     public:
    12.     Image(string,bool);
    13.     void Blit(SDL_Rect*, SDL_Rect*);
    14.     void setTexture(GLuint);
    15. };
    16. void DrawGL(void);
    17. #endif


    fichier affichage.cpp
    1. #include "affichage.h"
    2. extern Moteur moteur;
    3. Image::Image(string filename, bool useMipMap)
    4. {
    5.     GLuint glID;
    6.     SDL_Surface * picture_surface = NULL;
    7.     SDL_Surface *gl_surface = NULL;
    8.     SDL_Surface * gl_fliped_surface = NULL;
    9.     Uint32 rmask, gmask, bmask, amask;
    10.     picture_surface = IMG_Load(filename.c_str());
    11.     if (picture_surface == NULL)
    12.         die("Could not load image");
    13. #if SDL_BYTEORDER == SDL_BIG_ENDIAN
    14.     rmask = 0xff000000;
    15.     gmask = 0x00ff0000;
    16.     bmask = 0x0000ff00;
    17.     amask = 0x000000ff;
    18. #else
    19.     rmask = 0x000000ff;
    20.     gmask = 0x0000ff00;
    21.     bmask = 0x00ff0000;
    22.     amask = 0xff000000;
    23. #endif
    24.     SDL_PixelFormat format = *(picture_surface->format);
    25.     format.BitsPerPixel = 32;
    26.     format.BytesPerPixel = 4;
    27.     format.Rmask = rmask;
    28.     format.Gmask = gmask;
    29.     format.Bmask = bmask;
    30.     format.Amask = amask;
    31.     gl_surface = SDL_ConvertSurface(picture_surface,&format,SDL_SWSURFACE);
    32.     gl_fliped_surface = flipSurface(gl_surface);
    33.     glGenTextures(1, &glID);
    34.     glBindTexture(GL_TEXTURE_2D, glID);
    35.     if (useMipMap)
    36.     {
    37.         gluBuild2DMipmaps(GL_TEXTURE_2D, 4, gl_fliped_surface->w,
    38.                           gl_fliped_surface->h, GL_RGBA,GL_UNSIGNED_BYTE,
    39.                           gl_fliped_surface->pixels);
    40.         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,
    41.                         GL_LINEAR_MIPMAP_LINEAR);
    42.     }
    43.     else
    44.     {
    45.         glTexImage2D(GL_TEXTURE_2D, 0, 4, gl_fliped_surface->w,
    46.                      gl_fliped_surface->h, 0, GL_RGBA,GL_UNSIGNED_BYTE,
    47.                      gl_fliped_surface->pixels);
    48.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    49.     }
    50.     glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    51.     largeur=gl_fliped_surface->w;
    52.     hauteur=gl_fliped_surface->h;
    53.     SDL_FreeSurface(gl_fliped_surface);
    54.     SDL_FreeSurface(gl_surface);
    55.     SDL_FreeSurface(picture_surface);
    56.     setTexture(glID);
    57. }
    58. SDL_Surface* Image::flipSurface(SDL_Surface * surface)
    59. {
    60.     int current_line,pitch;
    61.     SDL_Surface * fliped_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
    62.                                    surface->w,surface->h,
    63.                                    surface->format->BitsPerPixel,
    64.                                    surface->format->Rmask,
    65.                                    surface->format->Gmask,
    66.                                    surface->format->Bmask,
    67.                                    surface->format->Amask);
    68.     SDL_LockSurface(surface);
    69.     SDL_LockSurface(fliped_surface);
    70.     pitch = surface->pitch;
    71.     for (current_line = 0; current_line < surface->h; current_line ++)
    72.     {
    73.         memcpy(&((unsigned char* )fliped_surface->pixels)[current_line*pitch],
    74.                &((unsigned char* )surface->pixels)[(surface->h - 1  -
    75.                                                     current_line)*pitch],
    76.                pitch);
    77.     }
    78.     SDL_UnlockSurface(fliped_surface);
    79.     SDL_UnlockSurface(surface);
    80.     return fliped_surface;
    81. }
    82. void DrawGL()
    83. {
    84.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    85.     glMatrixMode(GL_MODELVIEW);
    86.     glLoadIdentity();
    87.     moteur.affichage();
    88.     glFlush();
    89.     SDL_GL_SwapBuffers();
    90. }
    91. void Image::Blit(SDL_Rect* tmpsrc, SDL_Rect *tmpdest)
    92. {
    93.     SDL_Rect dest;
    94.     float srcx,srcy,srcw,srch;
    95.     if(tmpdest==NULL)
    96.     {
    97.         dest.x=0;
    98.         dest.y=600;
    99.         dest.h=600;
    100.         dest.w=800;
    101.     } else
    102.     {
    103.         dest.x=tmpdest->x;
    104.         dest.y=600-tmpdest->y;
    105.         dest.w=tmpdest->w;
    106.         dest.h=tmpdest->h;
    107.     }
    108.     if(tmpsrc==NULL)
    109.     {
    110.         srcx=0;
    111.         srcy=1;
    112.         srch=1;
    113.         srcw=1;
    114.     } else
    115.     {
    116.         srcx=(float)tmpsrc->x/largeur;
    117.         srcy=1-((float)tmpsrc->y/hauteur);
    118.         srcw=(float)tmpsrc->w/largeur;
    119.         srch=(float)tmpsrc->h/hauteur;
    120.     }
    121.     glEnable(GL_TEXTURE_2D);
    122.     glBindTexture(GL_TEXTURE_2D, image);
    123.     glBegin(GL_QUADS);
    124.         glTexCoord2f(srcx,srcy);
    125.         glVertex2d(dest.x,dest.y);
    126.         glTexCoord2f(srcx,srcy-srch);
    127.         glVertex2d(dest.x,dest.y-dest.h);
    128.         glTexCoord2f(srcx+srcw,srcy-srch);
    129.         glVertex2d(dest.x+dest.w,dest.y-dest.h);
    130.         glTexCoord2f(srcx+srcw,srcy);
    131.         glVertex2d(dest.x+dest.w,dest.y);
    132.     glEnd();
    133.     glDisable(GL_TEXTURE_2D);
    134. }
    135. void Image::setTexture(GLuint t)
    136. {
    137.     image=t;
    138. }


    Quand je charge une image, pas de problème, le chargement se passe bien (je teste toujours le chargement de mes images). L'image est bien chargé, elle est bien converti en texture OpenGL, les dimensions de "blittage" que je fourni à ma fonction sont bien prises en compte mais surprise : il ne m'affiche pas l'image chargé mais une surface blanche, et ceux quelque soit l'image ou le format d'image que je charge.

    Pour ce qui est des fonctions de chargement d'image, de conversion de SDL_Surface en texture OpenGL ainsi que la fonction qui permet de faire subir une rotation à ma surface, elle ne présente en théorie aucun problème. Elles ont été testé et approuvé étant donnée qu'elles proviennent directement du tuto de kayl sur OpenGL (section C des tutoriels). Je n'ai rien modifié dans ces fonctions!

    Je ne vois vraiment pas d'où vient l'erreur, surtout que mon code fonctionnait à merveille avant le passage à une classe, et que pour faire ce changement, je n'ai vraiment pas modifié grand chose!

    Merci d'avance si vous trouvez une solution à mon problème, qui peut venir de ma méthode ou d'une ligne de code pas clair. (Pour info : le compilo ne râle pas, pas même un warning)!


    Autre information :
    J'utilise mon objet de type image dans une classe nommée Menu. Je le fais comme ceci:
    Membre de la classe Menu:
    1. Image* bg;


    Dans le constructeur de Menu:
    1. bg=new Image("images/menu.jpg", true);


    Dans le destructeur:
    1. delete bg;


    Et dans la fonction d'affichage du Menu (qui est elle-même appelé par la fonction affichage de la classe Moteur comme vous l'avez vu dans le fichier affichage.cpp) :
    1. bg->Blit(NULL, NULL);
    • Partager sur Facebook
    • Partager sur Twitter
      18 novembre 2007 à 12:03:59

      Utilise la SFML qui utilise OpenGL.
      http://sfml.sourceforge.net/index-fr.php
      Il y a des tutos et est très facile d'utilisation.
      • Partager sur Facebook
      • Partager sur Twitter
        18 novembre 2007 à 17:50:06

        C'est pas vraiment ce que j'attendais. Je connais effectivement la librairie SFML et j'ai déjà programmé 2-3 trucs avec pour m'y essayer, mais mon but en fait est de mieux comprendre l'OpenGL directement, pas de passer par une librairie qui fera le travail pour moi.

        J'y viendrai par la suite mais j'ai envie de voir plus le coeur du fonctionnement, c'est pour ça que j'essaye de developper cette fonction de blittage moi-même en OpenGL.

        Par la suite, lorsque j'aurai bien tout compris, je n'hésiterais pas à passer à la SFML par contre!
        • Partager sur Facebook
        • Partager sur Twitter
          18 novembre 2007 à 20:26:35

          Tu as mis srcy à 1, ce qui est probablement faux.
          Pareil pour dest.y que tu as mis à 600.
          • Partager sur Facebook
          • Partager sur Twitter
            18 novembre 2007 à 21:05:36

            Non c'est correct également. En OpenGL, le repère n'est pas

            0---------------1
            |               |
            |               |
            |               |
            |               |
            1---------------1


            mais :

            1---------------1
            |               |
            |               |
            |               |
            |               |
            0---------------1


            Donc mes valeurs sont correctes! D'ailleurs l'image s'affiche bien au bon endroit, donc le problème ne vient pas de là. Même si je m'étais trompé dans ces valeurs, l'effet de cette erreur serait une image mal positionné, pas une image corrompu. Là ça se positionne bien, mais au lieu d'avoir mon image qui s'affiche, c'est du blanc (par dessus mon fond noir).
            • Partager sur Facebook
            • Partager sur Twitter
              18 novembre 2007 à 23:03:36

              Exact, c'est juste que j'ai l'habitude de commencer par 0,0 .
              Essaye quand même d'afficher le rectangle en mettant les coordonnées dans le programme.
              Sinon il doit y avoir un problème du côté du chargement.
              • Partager sur Facebook
              • Partager sur Twitter

              [OpenGL, SDL]Blit de surface

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown