Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Texture Mapping in OpenGL using Class CImage

5.00/5 (6 votes)
5 Aug 2016CPOL2 min read 16.6K   1.1K  
Texture Mapping in OpenGL from any Image File in any format using Class CImage(just call the File Name).

Introduction

The texture mapping implementation in OpenGL is a tiresome procedure. And sometimes it is worth it to have some simple operation just calling the name of the image file for texture mapping without a lot of stages with the conditions implementation required.

Background

The procedure of texture mapping implementation in OpenGL just calling the name of the image file has been developed with the application of the class CImage. The demo project ImgTexture has been derived from the standard MFC Cube Sample project renamed with the CodeProject ProjRename program.

Using the Code

The global procedure LoadImgTexture(LPCTSTR fName) and two related procedures GetImgBitmap(CImage * pImg) and LoadGLTexture(BITMAP * pBm) are located in the GlobGLTexture.cpp file inserted into ImgTexture project with the menu PROJECT->Add Existing Item... command.

The procedure for texture mapping:

 GLuint  LoadImgTexture(LPCTSTR fName)      //Load texture from Image file
{
	CImage img;
	HRESULT hResult = img.Load(fName);  //Standart procedure of CImage loading
	if (FAILED(hResult)) {
		CString fmt;
		fmt.Format(_T("Error %d\n%s"), hResult, _com_error(hResult).ErrorMessage());
		MessageBox(NULL, fmt + _T("\nin file:\n") + (CString)fName, _T("Error:"), MB_OK | MB_ICONERROR);
		return FALSE;
	}//if(FAILED(hResult))

	CBitmap * pBm = NULL;
	if (img.GetBPP() != 24)                                  //if Bitmap format not compatible with GL_BGR_EXT 
	{
		CImage tmg;
		tmg.Create(img.GetWidth(), img.GetHeight(), 24); //Create CImage compatible with GL_BGR_EXT
		img.BitBlt(tmg.GetDC(), CPoint(0, 0));           //Copy Original Image to the environment created
		pBm = GetImgBitmap(&tmg);                        //Get the class CBitmap from CImage class
	}
	else
		pBm = GetImgBitmap(&img);                        //Get the class CBitmap from CImage class

	BITMAP BMP;
	pBm->GetBitmap(&BMP);           //Standard procedure of BITMAP structure derived from CBitmap class
	return  LoadGLTexture(&BMP);	//Load Texture from BITMAP structure
   
}

The image from the image file loaded with standard CImage procedure. The default format of the image 24 bit per pixel expected. If the format of the image differes from the default then 24 bit per pixel environment created and the original image is copied into the new one.

And the CBitmap class draws upon the CImage class:

    CBitmap * GetImgBitmap(CImage * pImg)      //Get the class CBitmap from CImage class
{
	if (pImg == NULL)
		return NULL;

	CDC * pDC = new CDC;
	if (!pDC->CreateCompatibleDC(CDC::FromHandle(pImg->GetDC())))
		return NULL;
	CBitmap * pBm = new CBitmap;
	pBm->CreateCompatibleBitmap(CDC::FromHandle(pImg->GetDC()), pImg->GetWidth(), pImg->GetHeight());

	CBitmap * pBmOld = pDC->SelectObject(pBm);
	pImg->BitBlt(pDC->m_hDC, CPoint(0, 0));
	pDC->DeleteDC();

	return pBm;
}

The BITMAP structure draws upon the CBitmap class and implemetnted into texture with the standard OpenGL procedures with the format GL_BGR_EXT corresponding to 24 bit per pixel format in BITMAP structure:

GLuint LoadGLTexture(BITMAP * pBm)     //Load Texture from BITMAP structure
{
	GLuint texi;						//Name of the new texture
glGenTextures(1, &texi);					//Name of the new texture generation
	glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
	glBindTexture(GL_TEXTURE_2D, texi);			//Connection to texture mapping

	gluBuild2DMipmaps(GL_TEXTURE_2D, 3, pBm->bmWidth, pBm->bmHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, pBm->bmBits);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	return texi;                                //the name assigned to the texture created
}

In the original project just CImgTextureView class has a few changes:

three variables inserted:

int m_texNum;             //Current order number of the name of the texture 
CWordArray m_globTexture; //Array of the textures' names available	
int m_view_type;          //View performance:VIEW_DEFAULT or VIEW_TEXTURE
enum VIEW_TYPE
{
	VIEW_DEFAULT,           //Original Cube Sample View
	VIEW_TEXTURE,           //Texture View
};

the original CImgTextureView::Init() procedure with the procedures related remains unchanged; in CImgTextureView::OnCreate procedure in demo purposes the two lines of the texture implemetation from the image files in the Data folder of the root directory located:

            int CImgTextureView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	Init(); // initialize OpenGL
	m_globTexture.Add((WORD)LoadImgTexture(_T("Data/MSUN.bmp"))); //you may insert here any image files in any pathway valid
	m_globTexture.Add((WORD)LoadImgTexture(_T("Data/famrt.bmp")));//and as much as you like 
	return 0;
} ;

you may insert here any image files in any pathway valid and as much as you like; in the original CImgTextureView::DrawScene procedure the block of texture handling inserted:

case VIEW_TEXTURE:

        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, (GLuint)m_globTexture.GetAt(m_texNum));

        glBegin(GL_QUADS);

        glColor3f(1.0f, 1.0f, 1.0f);
        // Front Face
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
        glTexCoord2f(2.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
        glTexCoord2f(2.0f, 2.0f); glVertex3f(1.0f, 1.0f, 1.0f);
        glTexCoord2f(0.0f, 2.0f); glVertex3f(-1.0f, 1.0f, 1.0f);


        // Back Face
        glTexCoord2f(2.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
        glTexCoord2f(2.0f, 2.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 2.0f); glVertex3f(1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f);
        // Top Face
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, 1.0f, 1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
        // Bottom Face
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, -1.0f, -1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
        // Right face
        glTexCoord2f(1.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(1.0f, 1.0f, 1.0f);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
        // Left Face
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
        glEnd();

        glDisable(GL_TEXTURE_2D);
        break;

all the follows Menu and Accelerator Commands has been done with standard AppWizard technologies.

Application Demo Menu and Keyboard Commands

Some menu and some special Accelerator keys arranged in order to demonstrate the ImgTexture project implementation:

  • Menu File->Open - selecting the file with the image for texture mapping;
  • Menu View->Default - original Cube performance;
  • Menu View->Texture - current texture performance;
  • Menu View->Next Texture - next texture performance(also Right Arrow click);
  • Menu View->Prev Texture - previous texture performance(also Left Arrow click);

Points of Interest

The technology provided above is an attempt to demonstrate one of the simple texture implementation possibilities. The project has been developed in MFC platform. Nevertheless the GlobGLTexture.cpp procedures are also valid in Win32 and are acceptable for use in the Mobile applications.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)