OpenGL Texture Mapping with CImage Class

在OpenGL中实现纹理映射是一个繁琐的过程。有时,希望有一个简单的操作,只需调用图像文件的名称即可进行纹理映射,而不需要经过许多阶段的条件实现。

在OpenGL中,通过调用图像文件名称实现纹理映射的程序已经开发出来,这得益于CImage类的应用。演示项目ImgTexture是从标准的MFC Cube Sample项目派生出来的,使用CodeProject的ProjRename程序重命名。

使用代码

全局过程LoadImgTexture(LPCTSTR fName)和两个相关过程GetImgBitmap(CImage * pImg)和LoadGLTexture(BITMAP * pBm)位于GlobGLTexture.cpp文件中,该文件通过使用菜单命令PROJECT->Add Existing Item...插入到ImgTexture项目中。

纹理映射的过程如下:

GLuint LoadImgTexture(LPCTSTR fName) { CImage img; HRESULT hResult = img.Load(fName); 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; } CBitmap * pBm = NULL; if (img.GetBPP() != 24) { CImage tmg; tmg.Create(img.GetWidth(), img.GetHeight(), 24); img.BitBlt(tmg.GetDC(), CPoint(0, 0)); pBm = GetImgBitmap(&tmg); } else { pBm = GetImgBitmap(&img); } BITMAP BMP; pBm->GetBitmap(&BMP); return LoadGLTexture(&BMP); }

使用标准的CImage过程加载图像文件。默认情况下,图像格式为每像素24位。如果图像格式与默认格式不同,则创建一个每像素24位的环境,并将原始图像复制到新环境中。

CBitmap类依赖于CImage类:

CBitmap * GetImgBitmap(CImage * pImg) { 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; }

BITMAP结构依赖于CBitmap类,并使用标准的OpenGL程序实现纹理,格式为GL_BGR_EXT,对应于BITMAP结构中的每像素24位格式:

GLuint LoadGLTexture(BITMAP * pBm) { GLuint texi; glGenTextures(1, &texi); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glBindTexture(GL_TEXTURE_2D, texi); 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; }

在原始项目中,CImgTextureView类有一些变化:插入了三个变量:int m_texNum; // 当前纹理名称的顺序号 CWordArray m_globTexture; // 可用纹理名称的数组 int m_view_type; // 视图性能:VIEW_DEFAULT或VIEW_TEXTURE enum VIEW_TYPE { VIEW_DEFAULT, // 原始Cube Sample视图 VIEW_TEXTURE, // 纹理视图 };

原始的CImgTextureView::Init()过程及其相关过程保持不变;在CImgTextureView::OnCreate过程中,出于演示目的,在根目录的Data文件夹中实现了来自图像文件的两条纹理实现:

int CImgTextureView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; Init(); m_globTexture.Add((WORD)LoadImgTexture(_T("Data/MSUN.bmp"))); m_globTexture.Add((WORD)LoadImgTexture(_T("Data/famrt.bmp"))); return 0; }

在原始的CImgTextureView::DrawScene过程中插入了纹理处理块:

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); 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); glEnd(); glDisable(GL_TEXTURE_2D); break;

所有后续的菜单和加速器命令都是使用标准AppWizard技术完成的。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485