Skip to main content
GameDev.net gamedev.net
🔒 Locked

Textures within C++ classes

Started by zoulou2356 Oct 6, 2008 at 6:38 AM 6 replies 1.2k views
Original Post
zoulou2356
zoulou2356
Hi all, I'm working on a program written in C++ with some class to represent the different objects to draw in OpenGL. I have some trouble with textures. Here is an example of what my program is doing : I have a main class which creates the OpenGL window and then draws the OpenGL scene (with the drawGLScene() function). The drawGLScene function will create objects from another class called Image and give them the ID of the texture needed to draw. After that there is a loop wich will call the draw() function of all the "Images" created before.

class Main {

   HDC		hDC;		     
   HGLRC	hRC;		     
   HWND		hWnd;		      
   HINSTANCE	hInstance;	
   GLuint      	texturesID[256]; // array containing id of the textures
   int         	nextTexID;       // id of the next texture
   Image *      img;
  

// public functions of the class
public:
   Main();
   ~Main();
  
private:
   void createGLWindow(int width, int height, int bits);
   int drawGLScene(GLvoid);
   GLvoid destroyGLWindow(GLvoid);
   GLuint getNextTextureID();
};
All the initialization is done in createGLWindow(). The textures are created this function with

glGenTextures(256, texturesID);
The problem is here : when I call the draw() function of the Image class, I bind the texture with:

glBindTexture(GL_TEXTURE_2D, texID);
And unfortunately, the texture is not drawn. I just have a blank square.

class Image {
   GLuint   texID;   // ID of the texture
   float    size;    // size of the picture

// public functions of the Information object
public:
   Information(LPCSTR file, float size, GLuint texID);
   ~Information();
   void draw(float x, float y);
};
So, my question is : is this possible to bind textures in a class when they have been created in another ? Thank you for your help. Xavier [Edited by - zoulou2356 on October 6, 2008 7:19:36 AM]
Sneftel
Sneftel
OpenGL doesn't care about your classes. The one and only thing that matters is whether the integer being passed to glBindTexture is the same that was passed to glBindTexture before. If it is, the same texture will be used.

Now, that obviously isn't the code you're using. If you want real help, I suggest you post your real code.
zoulou2356
zoulou2356
Thank you very much for your quick answer.

I will try to give you a more "real" code so you can better see what the problem is :

/* Public functions */// constructor of the objectImage::Image(LPCSTR file, float size, GLuint texID) : size (size), texID(texID){      HBITMAP hBmp = (HBITMAP) ::LoadImage (NULL, file , IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);      BITMAP BM;      GetObject (hBmp, sizeof (BM), &BM);      glPixelStorei(GL_UNPACK_ALIGNMENT, 4);            glBindTexture(GL_TEXTURE_2D, this->texID);            // creating the texture      glTexImage2D(GL_TEXTURE_2D, 0, 3, BM.bmWidth, BM.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BM.bmBits);      // giving the right parameters for the texture      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);}// function to draw an Imagevoid Image::draw(float x, float y){    // select the texture   glBindTexture(GL_TEXTURE_2D, texID);   // reset the modelView matrix   glLoadIdentity();   // positioning animation   glTranslatef(x, y, 0.0f);   // select white for background of animation   glColor3f(1.0f,1.0f,1.0f);   // draw animation   glBegin(GL_QUADS);      glTexCoord2f(1.0f, 1.0f); glVertex2f(-size/2.0f, size/2.0f); // top left      glTexCoord2f(0.0f, 1.0f); glVertex2f( size/2.0f, size/2.0f); // top right      glTexCoord2f(0.0f, 0.0f); glVertex2f( size/2.0f,  -size/2.0f); // bottom right      glTexCoord2f(1.0f, 0.0f); glVertex2f(-size/2.0f,  -size/2.0f); // bottom left   glEnd();}


and the main class :
/* Public funtions */// ConstructorMain::Main(){   // initializing the OpenGL variables to NULL   hDC  = NULL;   hRC  = NULL;   hWnd = NULL;   nextTexID = 0;}// main functionDWORD Main::run(LPVOID){   // creating the OpenGL window   createGLWindow(WIN_WIDTH, WIN_HEIGHT, WIN_BITS);   // creation of the image   img = new Image("data/image1.bmp", 20.0f, getNextTextureID());   // drawing loop   while(running){      drawGLScene();      SwapBuffers(hDC);				// swap Buffers (double buffering)      Sleep(1000/REFRESH_FREQ);   }   // Destroy the OpenGL window   destroyGLWindow();   return 0;}/* Private  funtions */// function to initialize and create an OpenGL windowvoid Main::createGLWindow(int width, int height, int bits){	GLuint		PixelFormat;			// PixelFormat for our OpenGL window	WNDCLASS	   wc;						// Windows class structure	DWORD		   dwExStyle;				// window extended style	DWORD		   dwStyle;				   // window style	RECT		   windowRect;				// rectangle representing our window	....      /* 	Here is the window creation like in NeHe's tutorials    */	   // OpenGL Initialisation   // Reset the Viewport	glViewport(0,0,width,height);	// Select the projection matrix	glMatrixMode(GL_PROJECTION);	// Reset the projection matrix	glLoadIdentity();										// Calculate the aspect ratio of the window	gluOrtho2D(-(width/2),(width/2),-(height/2),(height/2));	// Select the modelview matrix	glMatrixMode(GL_MODELVIEW);	// Reset the modelview matrix	glLoadIdentity();	// smooth shading	glShadeModel(GL_SMOOTH);	// white background (RGBA)	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);	// Depth buffer setup	glClearDepth(1.0f);	// Enable depth testing	glEnable(GL_DEPTH_TEST);	// Type of depth testing	glDepthFunc(GL_LEQUAL);	// Setup really nice perspective calculations	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);      	// creation of the OpenGL textures   	glGenTextures(256, texturesID);}// function to draw an OpenGL sceneint Main::drawGLScene(GLvoid){   // Clear screen and depth buffer   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   // Drawing a square in the center of the screen   // Reset the current modelview matrix   glLoadIdentity();   glTranslatef(0.0f, 0.0f, 0.0f);	// Color RGB --> black	glColor3f(0.0f,0.0f,0.0f);	glBegin(GL_QUADS);						glVertex2f(-10.0f, 10.0f);	// Top left		glVertex2f( 10.0f, 10.0f);	// Top right		glVertex2f( 10.0f,-10.0f);	// Bottom right		glVertex2f(-10.0f,-10.0f);	// Bottom left	glEnd();   (*img).draw();   return 0;}// function to get a texture numberGLuint Main::getNextTextureID(){   return texturesID[nextTexID++];}


Note that the run() function of the Main class is called by the entry point of the program.

I hope it will be easier to understand my problem with this code.
Thank you for your help.
Sneftel
Sneftel
For purposes of simplicity, I'd suggest just calling glGenTextures (with num=1) in Image's constructor... no reason it can't grab one for itself, rather than having to be fed one from a pool.

That's probably not your problem, though. At a first glance, the code there looks fine... step through in the debugger and make sure that the name being passed to glBindTexture is the same in the constructor and the draw() call, and make sure that it's not zero, but that's about it. My suspicion is that your error is not there, but in the texture creation. Call glGetError after the constructor... I'm guessing you'll find something.

Oh, and are you remembering to enable texturing?
zoulou2356
zoulou2356
Thank you for your help Sneftel.

Yes, texturing was enabled.
I used glGetError() as you mentionned and it helped me to discover something I didn't want to discover.

My application is separated into two different threads. One of them contains the main loop which calls the draw() functions, and the other can dynamically add new objects to draw.
With this system, the problem is that some OpenGL functions which may not be called between glBegin() and glEnd() are called between these two functions.

So I have to find a solution to do a mutual exclusion for this critical section.

Thank you again for your help.
Xavier
deadstar
deadstar
Just a suggestion, but isn't it easier to get these basics out of the way before you introduce threading to the project?

Of course, plan ahead for threading, but leave the implementation until later.
"The right, man, in the wrong, place, can make all the dif-fer-rence in the world..." - GMan, Half-Life 2   A blog of my SEGA Megadrive development adventures: http://www.bigevilcorporation.co.uk
Sneftel
Sneftel
Quote:
Original post by zoulou2356
My application is separated into two different threads. One of them contains the main loop which calls the draw() functions, and the other can dynamically add new objects to draw.

Will not work without being very careful. It isn't just a glBegin/glEnd thing: OpenGL is not reentrant. It is not intended to be used by multiple threads simultaneously. Your mutex will need to ensure that no two GL calls are active at any time, in addition to excluding calls during a glBegin/glEnd block.
zoulou2356
zoulou2356
Thank you for your answer.

My problem is solved now. In fact, the second thread is calling OpenGL functions only for texture initialization. However, OpenGL does not allow to have only one rendering context and one device context for two different threads.

The solutions was to do all the initialization part in only one thread. This thread (and this thread only) is responsible for the OpenGL calls.

Thank you for the help provided.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.