problem with bitmap texture

I already load bitmap into my texture and display it. Everything is okay, except the quality of image. It’s not as beautiful as original image.

I don’t know how to fix it.

I’m gonna explain my program in briefly. It’s similar navigation monitor. It has a triangle that symbolize for a car, the background is a map. This map is a bitmap file.
The size of the bitmap file is bigger than the size of my application’s window. So, I only show a small area of bitmap file.
Sometimes, the car move out the small area. So I need to show the next area.

To draw a bitmap, I have 2 options.
First one is glDrawPixels. If I use this function, it’s beautiful. But I don’t know how to load another small area.
Second is Texture Mapping, I can load another small area easily. the quality is not good.

I need a recommendation. Please help me.

Please define “not as beautiful”. A picture could convey a book’s worth of…well, words.
Maybe your texture gets filtered(if so, turn filtering to nearest, that’s what glDrawPixels does). Or your texture coordinates are wrong? Or your polygon is not positioned well on the screen? It’s not very clear from what you say.

This picture I use glDrawPixels Link Nice Picture <link>

This picture I use bitmap mapping Link Bad Picture


void CNavigationWnd::LoadTexture(CString strFileName)
{
	HBITMAP hBmp = (HBITMAP) ::LoadImage (NULL,
                        (LPCTSTR) strFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE |
                        LR_CREATEDIBSECTION);
	::GetObject (hBmp, sizeof (m_bmTexture), &m_bmTexture);

	//Generate one texture index.
	glGenTextures(1, &m_texName);
	//Tell OpenGL we will be working with that texture number.
	glBindTexture(GL_TEXTURE_2D, m_texName);
	//Set the parameters for the texture.
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    // Build the texture map
    // Could use glTexImage2D instead but then we would have to scale
    // the image to make it a power of 2.
    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, m_bmTexture.bmWidth, m_bmTexture.bmHeight, 
		GL_BGR_EXT, GL_UNSIGNED_BYTE, m_bmTexture.bmBits );
	glBindTexture(GL_TEXTURE_2D, 0);

	::glDeleteLists(1,1);
	BuildList();
	InvalidateRect(NULL);
}

void CNavigationWnd::BuildList()
{
	::glNewList(1,GL_COMPILE_AND_EXECUTE);
	
	// ---------------------------------------------------------
	//glPushMatrix();

	glScalef(m_fScale,m_fScale,0);


	if(m_bmTexture.bmBits != NULL)
	{
		//glDrawPixels(m_bmTexture.bmWidth, m_bmTexture.bmHeight,GL_BGR_EXT,GL_UNSIGNED_BYTE, m_bmTexture.bmBits);

		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, m_texName);

		glColor3f(1.0f,1.0f,1.0f);
		glBegin(GL_POLYGON);
			float fLeft = (float)(m_fX/m_bmTexture.bmWidth);
			float fRight = (float)((m_fX + m_iClientWidth)/m_bmTexture.bmWidth);

			float fTop = (float)((m_fY+ m_iClientHeight)/m_bmTexture.bmHeight);
			float fBottom = (float)(m_fY/m_bmTexture.bmHeight);

			//glTexCoord2f(0.0, 0.0); glVertex3f(0.0f, 0.0f, 0.0f);
   			glTexCoord2f(fLeft, fBottom); glVertex3f(0.0f, 0.0f, 0.0f);
   			//glTexCoord2f(0.0, 1.0); glVertex3f(0.0f, m_iClientHeight, 0.0f);
			glTexCoord2f(fLeft, fTop); glVertex3f(0.0f, m_iClientHeight, 0.0f);
   			//glTexCoord2f(1.0, 1.0); glVertex3f(m_iClientWidth, m_iClientHeight, 0.0f);
			glTexCoord2f(fRight, fTop); glVertex3f(m_iClientWidth, m_iClientHeight, 0.0f);
   			//glTexCoord2f(1.0, 0.0); glVertex3f(m_iClientWidth, 0.0f, 0.0f);
			glTexCoord2f(fRight, fBottom); glVertex3f(m_iClientWidth, 0.0f, 0.0f);
		glEnd();
		glDisable(GL_TEXTURE_2D);

	}	
	//glPopMatrix();

	glColor3f(1.0f,0.0f,0.0f);
	// OpenGL no' nguoc doi, ham glTranslatef la ham move lai vi tri cu sau khi quay
	// Ham gltranslatef la ham move toi vi tri toa do goc roi moi qua
	// Code phai doc tu dong 3, 2, 1.
	// Phai noi truoc khi ve, chu ve roi thi noi gi nua.
	glLoadIdentity(); // glLoadIdentity replaces the current matrix with the identity matrix
	glTranslatef(150.0f, 150.0f, 0.0f);// 1
	glRotatef(m_fRotatedAngle,0.0f,0.0f,1.0f);// 2
	glTranslatef(-150.0f, -150.0f, 0.0f);// 3

	glBegin(GL_TRIANGLES);
		glVertex3f(150.0f + m_fX, 175.0f + m_fY, 0.0f);
		/*glColor3f(1.0f,0.0f,0.0f);*/
		glVertex3f(200.0f + m_fX, 150.0f + m_fY, 0.0f);
		//glColor3f(1.0f,0.0f,0.0f);
		glVertex3f(150.0f  + m_fX, 150.0f + m_fY, 0.0f);
	glEnd();


	// -----------------------------------------------------------
	::glEndList();
}

m_fX and m_fY is the new position of small area that took from original picture

@Y-tension: I changed the filter from linear to nearest, but it’s worse than before, like this

Link View Full Image

The solution my friend is very simple. gluBuildMipmaps will distort your image if dimensions are not a power of 2.
If you have a newer GPU(>= OpenGL 2.0) you can use non power of 2 textures so just load the texture as is and use automatic mipmap generation through OpenGL (glTextureParameter(GL_GENERATE_MIPMAP, GL_TRUE) or glGenerateMipmapsEXT(GL_TEXTURE_2D) from the framebuffer object extension), not GLU(which is deprecated anyway). Alternatively, load your texture as a subtexture of a larger power of 2 texture and modify your texture coordinates accordingly. One of these solutions should get rid of blurring.

For best results, use anisotropic filtering or GL_LINEAR_LINEAR(GL_LINEAR does not use mipmaps) for minification.

oh … thanks Y-tension … nice recommendation.
it so useful for me.

Well, I hope it helps too,apart from being nice :). Happy coding!