计算机图形学-纹理映射


先放个图


利用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);
}




  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用OpenGL绘制国旗可以通过以下步骤实现: 1. 创建OpenGL上下文和窗口。 2. 设置绘制区域和视口。 3. 设置绘制颜色和深度缓冲区。 4. 绘制国旗的红色背景。 5. 绘制五颗黄色的五角星。可以使用OpenGL的绘制多边形功能来绘制五角星,也可以使用纹理映射来贴上五角星的图案。 6. 交换前后缓冲区,显示绘制结果。 以下是一个简单的OpenGL绘制国旗的示例代码: ``` #include <GL/glut.h> void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glColor3f(1.0, 0.0, 0.0); // 设置绘制颜色为红色 glBegin(GL_QUADS); glVertex2f(-1.0, 1.0); glVertex2f(-1.0, -1.0); glVertex2f(1.0, -1.0); glVertex2f(1.0, 1.0); // 绘制国旗的红色背景 glEnd(); glColor3f(1.0, 1.0, 0.0); // 设置绘制颜色为黄色 glBegin(GL_POLYGON); glVertex2f(-0.5, 0.5); glVertex2f(-0.25, 0.25); glVertex2f(0.0, 0.5); glVertex2f(0.25, 0.25); glVertex2f(0.5, 0.5); glVertex2f(0.375, 0.25); glVertex2f(0.5, 0.0); glVertex2f(0.375, -0.25); glVertex2f(0.5, -0.5); glVertex2f(0.25, -0.375); glVertex2f(0.0, -0.5); glVertex2f(-0.25, -0.375); glVertex2f(-0.5, -0.5); glVertex2f(-0.375, -0.25); glVertex2f(-0.5, 0.0); glVertex2f(-0.375, 0.25); // 绘制五角星 glEnd(); glutSwapBuffers(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInitWindowSize(800, 600); glutInitWindowPosition(100, 100); glutCreateWindow("OpenGL Flag"); glutDisplayFunc(display); glutMainLoop(); return 0; } ``` 该示例代码使用了OpenGL的基本绘图功能,通过绘制红色背景和黄色五角星实现了绘制国旗的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值