《基于MFC的OpenGL编程》Part 9 Texture Mapping

《基于MFC的OpenGL编程》Part 9 Texture Mapping

     本文在第8篇文章的基础上,为立方体加入纹理映射的功能。

     本文源码链接

Texture Mapping

Texture Mapping in OpenGL is a fairly straightforward concept. Every texture is nothing but an image of some sort. Texture mapping is basically applying a texture to a surface. Textures can be 1D, 2D or even 3D. A 1D texture is an image with either a width or a height, not both. They are not very useful. 2D textures have both width and height and are very useful. 3D textures are called Volume textures and are used in medical imaging applications for viewing CAT, MRI, and other 3D scans. We will look at using 2D textures in OpenGL as they are the most widely used in 3D Graphics.

Windows Bitmap Files

Images in Windows are typically stored inbitmap files. These images can be used as textures that will be applied to OpenGL surfaces. But before use them for texture mapping applications we shouldconvert them to an OpenGL format. So we essentially have toread a Windows Bitmap into an OpenGL image. We can use the Auxiliary library to do so. It takes care of all the trouble involved in performing this conversion. Once a texture map is read into memory, the individual elements are called texels, just like an image's individual elements are called pixels. We wouldn't be dealing with these texels as we would be using the Aux library routine auxDIBImageLoadA to perform the conversion for us. Also, we need to make sure that the image dimensions are a power of 2. OpenGL images that we are going to use as a texture must have dimensions of a power of 2. Thus 32X32, 64X64, 128X64 etc. are all valid image sizes to be used as texture maps.

Defining 2D Textures

To define a 2D texture image in OpenGL we call glTexImage2D (when we are not using Mipmapping).

Mipmapping

When texture mapping is used with animation scaling of images cause some visual artifacts. This can be avoided by generating textures of various sizes from a large original texture and letting OpenGL automatically switch between the textures of various sizes. This technique is called Mipmapping and the individual textures are called Mipmaps. We can use the function gluBuild2DMipMaps to construct a series of mipmaps.

Texture Modes

OpenGL defines three texturing modes for different types of rendering. The first is GL_MODULATE, which modulates the current lighting and color information with the texture image. GL_DECAL is the second mode which only uses the texture image. Color and Lighting information will not affect the texture's appearance. The last mode is GL_BLEND, in which the texture image is blended with the current texture color and the current lighting and color information.

Texture Filters

OpenGL uses texture filters to interpolate between the texture pixels. It provides two types of texture filters: the minification filter (GL_TEXTURE_MIN_FILTER) for polygons smaller than the texture image and the magnification filter (GL_TEXTURE_MAG_FILTER) for polygons that are larger than the texture image. We'll look at how we will use these later in the tutorial.

Texture Coordinates

Texture Coordinates associate a particular location in the texture image with vertices in a polygon. These coordinates determine how the texture is mapped onto the polygon. Texture coordinates lie between 0.0 and 1.0 in case of 2D textures.

Texture Wrapping

When texture coordinates go outside the range of 0.0 to 1.0, they are either clamped to the surface or repeated. This can be specified by setting theGL_TEXTURE_WRAP_* parameter appropriately, to either GL_CLAMPor GL_REPEAT.

Texture Objects

Texture objects are a way of loading and maintaining multiple textures in memory without loading them each time before they are used. They are an optimization feature introduced recently in OpenGL.

1、CMy2OpenGLView类中加入下列变量,分别代表纹理环绕,纹理过滤,纹理模式的参数。

   GLdouble m_texWrap, m_texFilter, m_texMode;  
    //All Texture Names
     GLuint m_Texture[3]; //保存纹理对象的名称


 并在构造函数CMy2OpenGLView::CMy2OpenGLView()中加入:

    m_texWrap = GL_CLAMP;
    m_texMode = GL_DECAL;
    m_texFilter = GL_NEAREST;

2、加载纹理对象。

void CMy2OpenGLView::LoadGLTextures()
{
    //Create Texture Names
    glGenTextures(3, m_Texture);
    LoadTexture("Apple.bmp",0);
    LoadTexture("Fauve.bmp",1);
    LoadTexture("Flower.bmp",2);
}


void CMy2OpenGLView::LoadTexture(CString fileName, int texName)
{
	//Load Texture
    AUX_RGBImageRec* m_texture;
    m_texture = auxDIBImageLoad((const char*)fileName);
    if(!m_texture)
    {
        MessageBox("Picture could not be loaded");
        exit(1);
    }
    glBindTexture(GL_TEXTURE_2D, m_Texture[texName]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_texWrap);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_texWrap);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_texFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_texFilter);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_texMode);
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, m_texture->sizeX,m_texture->sizeY, GL_RGB, GL_UNSIGNED_BYTE, m_texture->data);
}

3、加入控制纹理映射效果的各个菜单项及其事件处理程序

void CMy2OpenGLView::LoadGLTextures()
{
    //Create Texture Names
    glGenTextures(3, m_Texture);
    LoadTexture("1.bmp",0);
    LoadTexture("2.bmp",1);
    LoadTexture("1.bmp",2);
}


void CMy2OpenGLView::LoadTexture(CString fileName, int texName)
{
	//Load Texture
    AUX_RGBImageRec* m_texture;
    m_texture = auxDIBImageLoad((const char*)fileName);
    if(!m_texture)
    {
        MessageBox("Picture could not be loaded");
        exit(1);
    }
    glBindTexture(GL_TEXTURE_2D, m_Texture[texName]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_texWrap);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_texWrap);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_texFilter);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_texFilter);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m_texMode);
    gluBuild2DMipmaps(GL_TEXTURE_2D, 3, m_texture->sizeX,m_texture->sizeY, GL_RGB, GL_UNSIGNED_BYTE, m_texture->data);
}

void CMy2OpenGLView::OnTexturewrapGlclamp() 
{
	// TODO: Add your command handler code here
	m_texWrap = GL_CLAMP;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturewrapGlclamp(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texWrap == GL_CLAMP)
		pCmdUI->SetRadio();
	else
		pCmdUI->SetRadio(FALSE);
}

void CMy2OpenGLView::OnTexturewrapGlrepeat() 
{
	// TODO: Add your command handler code here
	m_texWrap=GL_REPEAT;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturewrapGlrepeat(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texWrap==GL_REPEAT)
	{
		pCmdUI->SetRadio(TRUE);
	} 
	else
	{
		pCmdUI->SetRadio(FALSE);
	}
}

void CMy2OpenGLView::OnTexturefilterGlnearest() 
{
	// TODO: Add your command handler code here
	m_texFilter =GL_NEAREST;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturefilterGlnearest(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texFilter==GL_NEAREST)
	{
		pCmdUI->SetRadio();
	} 
	else
	{
		pCmdUI->SetRadio(FALSE);
	}
}

void CMy2OpenGLView::OnTexturefilterGllinear() 
{
	// TODO: Add your command handler code here
	m_texFilter=GL_LINEAR;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturefilterGllinear(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texFilter==GL_LINEAR)
	{
		pCmdUI->SetRadio();
	} 
	else
	{
		pCmdUI->SetRadio(FALSE);
	}
}

void CMy2OpenGLView::OnTexturemodeGlmodulate() 
{
	// TODO: Add your command handler code here
	m_texMode=GL_MODULATE;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturemodeGlmodulate(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texMode==GL_MODULATE)
	{
		pCmdUI->SetRadio();
	} 
	else
	{
		pCmdUI->SetRadio(FALSE);
	}
}

void CMy2OpenGLView::OnTexturemodeGldecal() 
{
	// TODO: Add your command handler code here
	m_texMode=GL_DECAL;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturemodeGldecal(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texMode==GL_MODULATE)
	{
		pCmdUI->SetRadio();
	} 
	else
	{
		pCmdUI->SetRadio(FALSE);
	}
}

void CMy2OpenGLView::OnTexturemodeGlblend() 
{
	// TODO: Add your command handler code here
	m_texMode=GL_BLEND;
	LoadGLTextures();

	InvalidateRect(NULL,FALSE);
}

void CMy2OpenGLView::OnUpdateTexturemodeGlblend(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	if (m_texMode==GL_BLEND)
	{
		pCmdUI->SetRadio();
	} 
	else
	{
		pCmdUI->SetRadio(FALSE);
	}
}

4、在InitializeOpenGL()中加入如下调用:

LoadGLTextures();//加载纹理

5、绘制函数修改如下:

	if (m_bCubeMove)//画一个自旋转的立方体
	{
		//	glClear(GL_COLOR_BUFFER_BIT |GL_DEPTH_BUFFER_BIT);
		glPolygonMode(GL_FRONT_AND_BACK,GL_LINES);
		
		glLoadIdentity();
		glTranslatef(0.0f,0.0f,-6.0f);
		glRotatef(m_xRot,1.0f,0.0f,0.0f);
		glRotatef(m_yRot,0.0f,1.0f,0.0f);
		//front face
		glBegin(GL_POLYGON);

		//glColor3f(1.0f,0.0f,1.0f);
		glTexCoord2f(0,0);
		glVertex3f(-1.0f,-1.0f,0.0f);
		//glColor3f(1.0f,1.0f,1.0f);
		glTexCoord2f(1,0);
		glVertex3f(-1.0f,1.0f,0.0f);
		//glColor3f(1.0f,1.0f,0.0f);
		glTexCoord2f(1,1);
		glVertex3f(1.0f,1.0f,0.0f);
		//glColor3f(0.0f,0.8f,1.0f);
		glTexCoord2f(0,1);
		glVertex3f(1.0f,-1.0f,0.0);
		glEnd();
		//glColor3f(1.0f,1.0f,1.0f);
		
		//back face
		glBegin(GL_POLYGON);
		//glColor3f(0.0f,0.5f,0.0f);
		glTexCoord2f(1,0);
		glVertex3f(-1.0,-1.0,-1.0);
		//glColor3f(1.0f,0.8f,10.0f);
		glTexCoord2f(1,1);
		glVertex3f(-1.0,1.0,-1.0);
		//glColor3f(0.0f,0.0f,1.0f);
		glTexCoord2f(0,1);
		glVertex3f(1.0,1.0,-1.0);
		//glColor3f(1.0f,1.0f,0.0f);
		glTexCoord2f(0,0);
		glVertex3f(1.0,-1.0,-1.0);
		glEnd();
		
		glColor3f(1.0f,0.0f,1.0f);
		//left face
		glBegin(GL_POLYGON);
		//glColor3f(1.0f,0.5f,0.0f);
		glTexCoord2f(1,0);
		glVertex3f(-1.0,-1.0,0.0);
		//glColor3f(0.8f,0.0f,0.0f);
		glTexCoord2f(1,1);
		glVertex3f(-1.0,1.0,0.0);
		//glColor3f(0.0f,0.0f,1.0f);
		glTexCoord2f(0,1);
		glVertex3f(-1.0,1.0,-1.0);
		//glColor3f(0.0f,0.6f,1.0f);
		glTexCoord2f(0,0);
		glVertex3f(-1.0,-1.0,-1.0);
		glEnd();
		
		glColor3f(0.0f,1.0f,0.0f);
		//right face
		glBegin(GL_POLYGON);
		//glColor3f(1.0f,0.0f,0.0f);
		glTexCoord2f(0,0);
		glVertex3f(1.0,-1.0,0.0);
		//glColor3f(0.0f,1.0f,1.0f);
		glTexCoord2f(1,0);
		glVertex3f(1.0,1.0,0.0);
		//glColor3f(0.0f,0.0f,1.0f);
		glTexCoord2f(1,1);
		glVertex3f(1.0,1.0,-1.0);
		//glColor3f(1.0f,0.0f,1.0f);
		glTexCoord2f(0,1);
		glVertex3f(1.0,-1.0,-1.0);
		glEnd();
		
		glColor3f(0.0f,1.0f,1.0f);
		//top face
		glBegin(GL_POLYGON);
		//glColor3f(0.0f,1.0f,0.0f);
		glTexCoord2f(0,0);
		glVertex3f(-1.0,1.0,0.0);
		//glColor3f(0.0f,0.0f,1.0f);
		glTexCoord2f(0,1);
		glVertex3f(-1.0,1.0,-1.0);
		//glColor3f(1.0f,0.0f,0.0f);
		glTexCoord2f(1,1);
		glVertex3f(1.0,1.0,-1.0);
		//glColor3f(0.0f,0.5f,0.8f);
		glTexCoord2f(1,0);
		glVertex3f(1.0,1.0,0.0);
		glEnd();
		
		//glColor3f(0.0f,0.0f,1.0f);
		//bottom face
		glBegin(GL_POLYGON);
		//glColor3f(0.0f,1.0f,0.0f);
		glTexCoord2f(0,1);
		glVertex3f(-1.0,-1.0,0.0);
		//glColor3f(0.0f,0.0f,1.0f);
		glTexCoord2f(0,0);
		glVertex3f(-1.0,-1.0,-1.0);
		//glColor3f(1.0f,0.0f,0.0f);
		glTexCoord2f(1,0);
		glVertex3f(1.0,-1.0,-1.0);
		//glColor3f(0.0f,0.5f,0.8f);
		glTexCoord2f(1,1);
		glVertex3f(1.0,-1.0,0.0);
		glEnd();

		glDisable(GL_TEXTURE_2D);
	}

运行效果:《基于MFC的OpenGL编程》Part 9 Texture Mapping_第1张图片《基于MFC的OpenGL编程》Part 9 Texture Mapping_第2张图片《基于MFC的OpenGL编程》Part 9 Texture Mapping_第3张图片《基于MFC的OpenGL编程》Part 9 Texture Mapping_第4张图片


你可能感兴趣的:(编程,mfc,3D,图形,OpenGL)