先放个图
利用MFC框架实现纹理映射
纹理映射主要包括纹理定义、纹理控制、纹理映射方式、纹理坐标和纹理对象等
1 首先创建位图类
class CBMPLoader
{
public:
CBMPLoader();
~CBMPLoader();
bool LoadBitmap(char *filename); //装载一个bmp文件
void FreeImage(); //释放图像数据
unsigned int ID; //生成纹理的ID号
int imageWidth; //图像宽度
int imageHeight; //图像高度
unsigned char *image; //指向图像数据的指针
};
2 位图类的实现
CBMPLoader::CBMPLoader()
{
/** 初始化成员值为0 */
image = 0;
imageWidth = 0;
imageHeight = 0;
}
CBMPLoader::~CBMPLoader()
{
FreeImage(); /**< 释放图像数据占据的内存 */
}
/** 装载一个位图文件 */
bool CBMPLoader::LoadBitmap(char *file)
{
FILE *pFile = 0; //文件指针;
/*创建位图文件信息和位图文件头结构*/
BITMAPINFOHEADER bitmapInfoHeader;
BITMAPFILEHEADER header;
unsigned char textureColors = 0;/**< 用于将图像颜色从BGR变换到RGB */
/** 打开文件,并检查错误 */
pFile = fopen(file, "rb");
if (pFile == 0) return false;
/** 读入位图文件头信息 */
fread(&header, sizeof(BITMAPFILEHEADER), 1, pFile);
/** 检查该文件是否为位图文件 */
if (header.bfType != BITMAP_ID)
{
fclose(pFile); /**< 若不是位图文件,则关闭文件并返回 */
return false;
}
/** 读入位图文件信息 */
fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, pFile);
/** 保存图像的宽度和高度 */
imageWidth = bitmapInfoHeader.biWidth;
imageHeight = bitmapInfoHeader.biHeight;
/** 确保读取数据的大小 */
if (bitmapInfoHeader.biSizeImage == 0)
bitmapInfoHeader.biSizeImage = bitmapInfoHeader.biWidth *
bitmapInfoHeader.biHeight * 3;
/** 将指针移到数据开始位置 */
fseek(pFile, header.bfOffBits, SEEK_SET);
/** 分配内存 */
image = new unsigned char[bitmapInfoHeader.biSizeImage];
/** 检查内存分配是否成功 */
if (!image) /**< 若分配内存失败则返回 */
{
delete[] image;
fclose(pFile);
return false;
}
/** 读取图像数据 */
fread(image, 1, bitmapInfoHeader.biSizeImage, pFile);
/** 将图像颜色数据格式进行交换,由BGR转换为RGB */
for (int index = 0; index < (int)bitmapInfoHeader.biSizeImage; index += 3)
{
textureColors = image[index];
image[index] = image[index + 2];
image[index + 2] = textureColors;
}
fclose(pFile); /**< 关闭文件 */
return true; /**< 成功返回 */
}
/** 释放内存 */
void CBMPLoader::FreeImage()
{
/** 释放分配的内存 */
if (image)
{
delete[] image;
image = 0;
}
}
3 编写测试类
extern GLfloat LightAmbient[];
extern GLfloat LightDiffuse[];
extern GLfloat LightSpecular[]; /**< 镜面光参数 */
extern GLfloat LightPosition[]; /**< 光源位置 */
class Example{
public:
bool Init(int cx ,int cy){
/** 用户自定义的初始化过程 */
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
//ResizeDraw(true); /**< 改变OpenGL窗口大小,直接调用子类的函数 */
glViewport(0, 0, cx, cy);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)cx / (GLfloat)cy, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D); /**< 启用纹理映射 */
if (!Texture.LoadBitmap("image.bmp")) /**< 载入位图文件 */
{
MessageBox(NULL, TEXT("装载位图文件失败!"), TEXT("错误"), MB_OK); /**< 如果载入失败则弹出对话框 */
return false;
}
glGenTextures(1, &Texture.ID); /**< 生成一个纹理对象名称 */
glBindTexture(GL_TEXTURE_2D, Texture.ID); /**< 创建纹理对象 */
/** 控制滤波 */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
/** 创建纹理 */
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, Texture.imageWidth,
Texture.imageHeight, GL_RGB, GL_UNSIGNED_BYTE,
Texture.image);
/** 设置光源的属性值 */
glLightfv(GL_LIGHT1, GL_AMBIENT, LightAmbient); /**< 设置环境光 */
glLightfv(GL_LIGHT1, GL_DIFFUSE, LightDiffuse); /**< 设置漫射光 */
glLightfv(GL_LIGHT1, GL_SPECULAR, LightSpecular); /**< 设置漫射光 */
glLightfv(GL_LIGHT1, GL_POSITION, LightPosition); /**< 设置光源位置 */
/** 启用光照和光源 */
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT1);
return true; /**< 成功返回 */
}
/**< 执行所有的初始化工作,如果成功函数返回true */
void Uninit(){
Texture.FreeImage(); /** 释放纹理图像占用的内存 */
glDeleteTextures(1, &Texture.ID); /**< 删除纹理对象 */
}
/**< 执行所有的卸载工作 */
void Draw(){
/** 用户自定义的绘制过程 */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); /**< 清楚缓存 */
glLoadIdentity();
/** 绘制过程 */
glTranslatef(0.0f, 0.0f, -7.0f);
glRotatef(rot, 1.0f, 1.0f, 0.0f);
/** 选择纹理 */
glBindTexture(GL_TEXTURE_2D, Texture.ID);
/** 开始绘制四边形 */
glBegin(GL_QUADS);
/// 前侧面
glNormal3f(0.0f, 0.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);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
/// 后侧面
glNormal3f(0.0f, 0.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);
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, -1.0f);
/// 顶面
glNormal3f(0.0f, 1.0f, 0.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);
glTexCoord2f(1.0f, 1.0f); glVertex3f(1.0f, 1.0f, -1.0f);
/// 底面
glNormal3f(0.0f, -1.0f, 0.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);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
/// 右侧面
glNormal3f(1.0f, 0.0f, 0.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);
glTexCoord2f(0.0f, 0.0f); glVertex3f(1.0f, -1.0f, 1.0f);
/// 左侧面
glNormal3f(-1.0f, 0.0f, 0.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);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd(); /**< 四边形绘制结束 */
glFlush(); /**< 强制执行所有的OpenGL命令 */
}
/** 用户自定义的程序变量 */
CBMPLoader Texture; /**< 位图载入类的对象 */
float rot = 1; /**< 用于旋转物体 */
};
4.
实现绘图
Example test;
GLfloat LightAmbient[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; /**< 环境光参数 */
GLfloat LightDiffuse[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /**< 漫射光参数 */
GLfloat LightSpecular[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; /**< 镜面光参数 */
GLfloat LightPosition[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; /**< 光源位置 */
void CTextureView::OnDraw(CDC* /*pDC*/)
{
CTextureDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 绘制场景
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
DrawPicture();
glPopMatrix();
// 交换缓冲区
SwapBuffers(wglGetCurrentDC());
}
void CTextureView::DrawPicture()
{
CRect rc; GetWindowRect(&rc);
int cx = rc.Width(); int cy = rc.Height();
test.Init(cx,cy);
test.Draw();
SetTimer(1, 1, NULL);
}
void CTextureView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (nIDEvent == 1){
test.rot += 1;
InvalidateRect(NULL, FALSE);
SetTimer(1, 1, NULL);
}
CView::OnTimer(nIDEvent);
}