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 :

Problème avec glBindTexture


Sujet :

OpenGL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Janvier 2005
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Janvier 2005
    Messages : 18
    Par défaut Problème avec glBindTexture
    Bonjour ,

    j'ai un problème qui en fait n'en est pas un !

    En fait j'essaye d'utiliser OpenGL avec wxWidgets via un wxGLCanvas.
    Je charge une image à l'aide de la classe wxImage, et j'essaye d'en faire une texture affichable à l'aide d'OpenGL.

    Pour se faire j'ai donc utilisé le tutoriel trouvé sur le wiki de wxWidgets, que j'ai adapté un petit peu.

    Le problème c'est que ça fonctionne parfaitement sur MacOSX, mais sur Windows XP quand j'essaye d'afficher j'ai une violente erreur et ça plante directement. J'ai réussi à isoler la ligne qui bloque le tout sur windows, du coup ça affiche une image blanche sans la texture donc.

    J'ai isolé d'où viens le problème, c'est la ligne suivante :
    Code GLSprite.cpp à la ligne 58 : Sélectionner tout - Visualiser dans une fenêtre à part
    glBindTexture(GL_TEXTURE_2D, image->getID()[0]);

    J'ai bien vérifié dans la classe GLImage si l'image était bien chargée, et c'est le cas, la taille est bien prise etc. Donc je ne sais pas trop d'où viens le problème puisque ça s'affiche au poil sur OS X.

    Voila le code :
    Code GLImage.h : 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
    #ifndef __GLImage
    	#define __GLImage
    #ifdef __WXMAC__
    	#include "OpenGL/glu.h"
    	#include "OpenGL/gl.h"
    	#include "GLUT/glut.h"
    #else
    	#include <wx/glcanvas.h>
    #endif
    #include <wx/wx.h>
    #include <wx/image.h>
    #include <cmath>
     
    namespace Graphics
    {
    	/**
             * GLImage contains an OpenGL representation of an image (i.e. a texture) wich
             * is dedicated to be rendered in an OpenGL scene. 
             * The asset of this class is to provide a convenient way to load image via wxImage
             * to an OpenGL representation wich can be directly rendered. 
             */
    	class GLImage
    	{
    	private:
    		GLuint* ID;
     
    	public:
    		int width,
    			height,
    			textureWidth,
    			textureHeight;
    		float textureCoordX,
    		      textureCoordY;
     
    		GLuint* getID();
    		GLImage();
    		GLImage(wxString path);
    		~GLImage();
    		int getWidth();
    		void load(wxString path);
    		GLuint* loadImage(wxString imagePath, int* imageWidth, int* imageHeight, int* textureWidth, int* textureHeight);
    	};
    }	
    #endif

    Code GLImage.cpp : 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
    166
    167
    168
    169
    #include "GLImage.h"
    #define HAS_ALPHA (img->HasAlpha() ?  4 : 3)
    #define IS_RGBA (img->HasAlpha() ?  GL_RGBA : GL_RGB)
     
    using Graphics::GLImage;
    using namespace std;
     
    /**
     * Default constructor.
     */
    GLImage::GLImage()
    {
    }
     
    /**
     * Constructor from the path to the image to load.
     * @param imagePath path to the image to load
     */
    GLImage::GLImage(wxString imagePath)
    {
        this->load(imagePath);
    }
     
    /**
     * Load an image.
     * @param imagePath path to the image to load
     */
    void GLImage::load(wxString imagePath)
    {
        ID = loadImage(imagePath, &width, &height, &textureWidth, &textureHeight);
     
        textureCoordX = width / (float)textureWidth;
        textureCoordY = height / (float)textureHeight;
    }
     
    /**
     * Get the OpenGL texture identifiant.
     * @return the OpenGL texture identifiant
     */
    GLuint* GLImage::getID()
    {
        return ID;
    }
     
    /**
     * Get the texture width.
     * @return the width of the texture
     */
    int GLImage::getWidth()
    {
        return width;
    }
     
    /**
     * Destructor
     */
    GLImage::~GLImage()
    {
        glDeleteTextures(1, ID);
    }
     
    /**
     * Load an image into it's OpenGL representation
     * @param imagePath the path to the image to load
     * @param imageWidth variable where the image's width is stored
     * @param imageHeight variable where the image's heigth is stored
     * @param textureWidth variable where the texture's width is stored
     * @param textureHeight variable where the texture's width is stored
     * @return the OpenGL texture representation of the image.
     */
    GLuint* GLImage::loadImage(wxString imagePath, int* imageWidth, int* imageHeight, int* textureWidth, int* textureHeight)
    {
    	wxImage * img = new wxImage(imagePath);
     
    	GLuint* ID = new GLuint[1];
    	glGenTextures(1, ID);
     
    	glBindTexture(GL_TEXTURE_2D, *ID);
     
    	// init image handlers
    	static bool firstRun = true;
    	if ( firstRun )
    	{
    		wxInitAllImageHandlers();
    		firstRun = false;
    	}
     
    	*imageWidth = img->GetWidth();
    	*imageHeight = img->GetHeight();
     
    	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     
    	float correctWidth  = log((float)*imageWidth) / log(2.0);
    	float correctHeight = log((float)*imageHeight) / log(2.0);
     
    	// check if image dimensions are a power of two
    	if ( (int)correctWidth == correctWidth && (int)correctHeight == correctHeight)
    	{
    		glTexImage2D(GL_TEXTURE_2D, 0, HAS_ALPHA, *imageWidth, *imageHeight, 0, IS_RGBA, GL_UNSIGNED_BYTE, img->GetData());
     
    		*textureWidth  = *imageWidth;
    		*textureHeight = *imageHeight;
     
    	}
    	else // resize the texture to match a power of 2
    	{
    		int newWidth = (int)pow(2.0, (int)ceil(correctWidth));
    		int newHeight = (int)pow(2.0, (int)ceil(correctHeight));
     
    		GLubyte	*bitmapData = img->GetData();
    		GLubyte *alphaData  = img->GetAlpha();
    		GLubyte	*imageData;
     
    		int old_bytesPerPixel = 3;
    		int bytesPerPixel     = HAS_ALPHA;
     
    		int imageSize = newWidth * newHeight * bytesPerPixel;
    		imageData     = (GLubyte *)malloc(imageSize);
     
    		int rev_val = *imageHeight - 1;
     
    		for (int y = 0; y < newHeight; ++y)
    		{
    			for (int x = 0; x < newWidth; ++x)
    			{
     
    				if ( x < *imageWidth && y < *imageHeight )
    				{
    					imageData[(x + y * newWidth) * bytesPerPixel] = 
    						bitmapData[(x + (rev_val-y) * *imageWidth) * old_bytesPerPixel];
     
    					imageData[(x+y*newWidth) * bytesPerPixel + 1] = 
    						bitmapData[(x + (rev_val-y) * *imageWidth) * old_bytesPerPixel + 1];
     
    					imageData[(x+y*newWidth) * bytesPerPixel + 2] = 
    						bitmapData[(x + (rev_val-y) * *imageWidth) * old_bytesPerPixel + 2];
     
    					if (bytesPerPixel == 4) 
    						imageData[(x + y * newWidth) * bytesPerPixel + 3] = 
    							alphaData[x + (rev_val-y) * *imageWidth];
    				}
    				else
    				{
    					imageData[(x + y * newWidth) * bytesPerPixel]  =  0;
    					imageData[(x + y * newWidth) * bytesPerPixel + 1]  =  0;
    					imageData[(x + y * newWidth) * bytesPerPixel + 2]  =  0;
    					if (bytesPerPixel == 4) 
    						imageData[(x + y * newWidth) * bytesPerPixel + 3]  =  0;
    				}
    			}
    		}
     
    		glTexImage2D(GL_TEXTURE_2D, 0, HAS_ALPHA, newWidth, newHeight, 0, IS_RGBA, GL_UNSIGNED_BYTE, imageData);
     
    		*textureWidth  = newWidth;
    		*textureHeight = newHeight;
     
    		delete imageData;
    	}
     
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 0);//GL_CLAMP_TO_EDGE);
    	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 0);//GL_CLAMP_TO_EDGE);
     
    	wxMessageBox(wxString::Format(wxT("id : %d"), *ID));
    	return ID;
    }

    Code GLSprite.h : 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
    #ifndef __GLSprite
    	#define __GLSprite
    #ifdef __WXMAC__
    	#include "OpenGL/gl.h"
    #else
    	#include <wx/glcanvas.h>
    #endif
    #include "wx/wx.h"
    #include "GLImage.h"
     
    namespace Graphics
    {
    	class GLSprite
    	{
    		private:
    		    GLImage* image;
    		    int x, y, angle, hotSpotX, hotSpotY;
    		    float xScale, yScale;
    		    bool xFlip, yFlip;
     
    		public:
    		    GLSprite(GLImage* img);
    			~GLSprite();
    		    /* des fonctions pour rotation etc... */
    		    void setImage(GLImage* image);
    		    GLImage* getImage();
    		    void render();
    	};
    }	
    #endif

    Code GLSprite.cpp : 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
    #include "GLSprite.h"
    using Graphics::GLSprite;
    using Graphics::GLImage;
     
    /**
     * This is a simple class built on top of OpenGL that manages drawing images in a higher-level and quicker way.
     */
    GLSprite::GLSprite(GLImage* img)
    {
        x = y = hotSpotX = hotSpotY = angle = 0;
        xScale = yScale = 1;
        xFlip = yFlip = false;
     
        if (img != NULL) 
    		this->setImage(img);
        else 
    		image = NULL;
    }
     
    GLSprite::~GLSprite()
    {
    	delete image;
    }
     
    void GLSprite::setImage(GLImage* image)
    {
        this->image = image;
    }
     
    Graphics::GLImage* GLSprite::getImage()
    {
    	return this->image;
    }
     
    void GLSprite::render()
    {
        if (image == NULL)
    	{
    		wxMessageBox(wxT("image vide"));
    		exit(1);
    	}
     
        glLoadIdentity();
        glTranslatef(x, y, 0);
     
        if (xScale != 1 || yScale != 1)
            glScalef(xScale, yScale, 1);
     
        if (angle)
            glRotatef(angle, 0,0,1);
     
        if (image->getID() == NULL)
    	{
    		wxMessageBox(wxT("ID vide"));
    		exit(1);
    	}
     
        glBindTexture(GL_TEXTURE_2D, image->getID()[0]);
     
        glBegin(GL_QUADS);
     
        glTexCoord2f(xFlip? image->textureCoordX : 0, yFlip? 0 : image->textureCoordY);
        glVertex2f(-hotSpotX, -hotSpotY);
     
        glTexCoord2f(xFlip? 0 : image->textureCoordX, yFlip? 0 : image->textureCoordY);
        glVertex2f(image->width - hotSpotX, -hotSpotY);
     
        glTexCoord2f(xFlip? 0 : image->textureCoordX, yFlip? image->textureCoordY : 0);
        glVertex2f(image->width - hotSpotX, image->height - hotSpotY);
     
        glTexCoord2f(xFlip? image->textureCoordX : 0, yFlip? image->textureCoordY : 0);
        glVertex2f(-hotSpotX, image->height - hotSpotY);
     
        glEnd();
    }

    Et finalement j'affiche l'image comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Graphics::GLSPrite * sprite = new Graphics::GLSprite(new Graphics::GLImage("sprite.bmp"));
    sprite->render();
    J'ai fait une recherche mais je n'ai pas trouvé de réponse pour le moment, donc si vous pouviez m'aider ça serait très sympathique

    Merci d'avance !

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    366
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 366
    Par défaut
    L'erreur est ici :0

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    GLuint* ID = new GLuint[1];
    tu redeclare une variable ID qui est locale a la methode . Comme cette variable a le meme nom que le membre de la classe image , le membre est masque !. Tu devrais ecrire quelque chose comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    ID = new GLuint[1]; /* qui est finalement equivalent a this->ID = ... */
    Question: pourquoi ne pas directement utilise un membre ID de type uint plutot que pointeur sur uint (qui force une allocation memoire) ?

  3. #3
    Membre averti
    Inscrit en
    Janvier 2005
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Janvier 2005
    Messages : 18
    Par défaut
    Malheureusement ça ne change rien, et puis la fonction loadImage renvoyais le GLuint* crée qui était donc assigné à ID (le membre de la classe).

    J'ai vraiment du mal à voir d'où peut venir l'erreur.
    Car finalement, même en commentant la ligne que j'ai indiqué dans mon premier message, ça s'affiche correctement sous MacOSX ce qui est en fait logique puisque je n'affiche qu'une seule image pour le moment, donc je ne fais qu'un appel à glBindTextures, donc ça unbind pas si je puis dire l'ancienne texture bindé à GL_TEXTURE_2D.

    En faisant ça sur Windows ça ne plante plus, par contre j'ai un rectangle blanc de la taille de l'image. Je peux donc supposer que l'image data n'est pas correctement lue ? Mais ça seulement sous Windows, ça me parait étrange . C'est un peu comme si l'appel à glGenTextures() n'avais pas d'effet. Bien sur je peux me tromper, je débute avec OpenGL, mais d'après le manuel j'ai à peu près compris comment s'enchainent les appels à ces fonctions.

    Pour l'instant je suis toujours dans le flou .

    Pour ta deuxième question, j'ai fait ça car ça me parait mieux pour gérer plusieurs Sprite qui partageraient une même texture (genre pour répéter l'affichage de cette texture par l'appel de plusieurs objets).

    Si vous avez d'autres idées je suis preneur !

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 15
    Par défaut
    De quelle taille est ta texture ?

    Sous osx la carte supporte peut-être les textures n'étant pas d'une puissance de 2 ?

  5. #5
    Membre averti
    Inscrit en
    Janvier 2005
    Messages
    18
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Janvier 2005
    Messages : 18
    Par défaut
    Citation Envoyé par lordheavy Voir le message
    De quelle taille est ta texture ?

    Sous osx la carte supporte peut-être les textures n'étant pas d'une puissance de 2 ?
    La texture fais du 195x16 mais j'ai testé également avec une image de taille 256x256 ça ne change rien.

    Le code donné dans mon premier message est censé créer une image de taille puissance de 2 en collant du noir pour remplir, donc ça devrais également charger l'image même si elle n'est pas de taille puissance de 2.

    Je vais tenter avec auxDIBImageLoad pour voir si le problème arrive avec ça, ce qui voudrais dire que ça viens du traitement via wxImage, mais du coup je perds le gain d'utilisation de wxImage qui est de pouvoir charger tout un tas de format différent, notamment le png .

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Ca serait pas un probleme de big ou little indian lors du chargement des textures ?

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

Discussions similaires

  1. Textures : problème avec glBindTexture
    Par Xander51 dans le forum OpenGL
    Réponses: 14
    Dernier message: 24/05/2007, 02h52
  2. [C++][Qt] Problème opengl avec glBindTexture
    Par quantik-revolution dans le forum OpenGL
    Réponses: 15
    Dernier message: 24/04/2006, 10h14
  3. Problème avec le type 'Corba::Any_out'
    Par Steven dans le forum CORBA
    Réponses: 2
    Dernier message: 14/07/2002, 18h48
  4. Problème avec la mémoire virtuelle
    Par Anonymous dans le forum CORBA
    Réponses: 13
    Dernier message: 16/04/2002, 16h10

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