OpenGL3D图形绘制/纹理映射

1.3D图形绘制

3D图形也是由2D的面片组合而成,一个需要注意的问题是所有的面片绘制要么是逆时针要么是顺时针,因此每三个点确定一个三角形或者每四个点确定一个四边形,再有余下的点时,按新的形状处理。以下以一个旋转的金字塔和立方体为例,

/*******************************************************************************************************************************************
*int DrawGLScene(GLvoid)		
*功能:绘图
*参数:无
*返回值:BOOL
********************************************************************************************************************************************/
int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// 清除屏幕和深度缓存
	glLoadIdentity();	// 重置当前的模型观察矩阵
	//添加绘图代码
	glTranslatef(-1.5f,0.0f,-6.0f);	// 左移 1.5 单位,并移入屏幕 6.0
	glRotatef(30.0f,0.0f,1.0f,0.0f);	// 绕Y轴旋转金字塔
	glBegin(GL_TRIANGLES);	// 绘制三角形
		//开启平滑着色模式
		glColor3f(1.0f,0.0f,0.0f);		// 红色
		glVertex3f( 0.0f, 1.0f, 0.0f);	// 三角形的上顶点 (前侧面)
		glColor3f(0.0f,1.0f,0.0f);		// 绿色
		glVertex3f(-1.0f,-1.0f, 1.0f);	// 三角形的左下顶点 (前侧面)
		glColor3f(0.0f,0.0f,1.0f);		// 蓝色
		glVertex3f( 1.0f,-1.0f, 1.0f);	// 三角形的右下顶点 (前侧面)

		glColor3f(1.0f,0.0f,0.0f);		// 红色
		glVertex3f( 0.0f, 1.0f, 0.0f);	// 三角形的上顶点 (右侧面)
		glColor3f(0.0f,0.0f,1.0f);		// 蓝色
		glVertex3f( 1.0f,-1.0f, 1.0f);	// 三角形的左下顶点 (右侧面)
		glColor3f(0.0f,1.0f,0.0f);		// 绿色
		glVertex3f( 1.0f,-1.0f, -1.0f);	// 三角形的右下顶点 (右侧面)

		glColor3f(1.0f,0.0f,0.0f);		// 红色
		glVertex3f( 0.0f, 1.0f, 0.0f);	// 三角形的上顶点 (后侧面)
		glColor3f(0.0f,1.0f,0.0f);		// 绿色
		glVertex3f( 1.0f,-1.0f, -1.0f);	// 三角形的左下顶点 (后侧面)
		glColor3f(0.0f,0.0f,1.0f);		// 蓝色
		glVertex3f(-1.0f,-1.0f, -1.0f);	// 三角形的右下顶点 (后侧面)

		glColor3f(1.0f,0.0f,0.0f);		// 红色
		glVertex3f( 0.0f, 1.0f, 0.0f);	// 三角形的上顶点 (左侧面)
		glColor3f(0.0f,0.0f,1.0f);		// 蓝色
		glVertex3f(-1.0f,-1.0f,-1.0f);	// 三角形的左下顶点 (左侧面)
		glColor3f(0.0f,1.0f,0.0f);		// 绿色
		glVertex3f(-1.0f,-1.0f, 1.0f);	// 三角形的右下顶点 (左侧面)
	glEnd();

	glLoadIdentity();	// 重置当前的模型观察矩阵
	glTranslatef(1.50f,0.0f,-7.0f);	// 右移1.5单位,并移入屏幕6个单位
	glRotatef(30.0f,1.0f,1.0f,1.0f);	// 绕XYZ轴旋转立方体
	glBegin(GL_QUADS);		//  绘制立方体
		//开启单调着色模式,保证立方体的每个面的颜色都不同
		glColor3f(0.0f,1.0f,0.0f);		// 一次性将当前色设置为绿色
		glVertex3f( 1.0f, 1.0f,-1.0f);	// 四边形的右上顶点 (顶面)
		glVertex3f(-1.0f, 1.0f,-1.0f);	// 四边形的左上顶点 (顶面)
		glVertex3f(-1.0f, 1.0f, 1.0f);	// 四边形的左下顶点 (顶面)
		glVertex3f( 1.0f, 1.0f, 1.0f);	// 四边形的右下顶点 (顶面)

		glColor3f(1.0f,0.5f,0.0f);		// 颜色改成橙色
		glVertex3f( 1.0f,-1.0f, 1.0f);	// 四边形的右上顶点(底面)
		glVertex3f(-1.0f,-1.0f, 1.0f);	// 四边形的左上顶点(底面)
		glVertex3f(-1.0f,-1.0f,-1.0f);	// 四边形的左下顶点(底面)
		glVertex3f( 1.0f,-1.0f,-1.0f);	// 四边形的右下顶点(底面)

		glColor3f(1.0f,0.0f,0.0f);		// 颜色改成红色
		glVertex3f( 1.0f, 1.0f, 1.0f);	// 四边形的右上顶点(前面)
		glVertex3f(-1.0f, 1.0f, 1.0f);	// 四边形的左上顶点(前面)
		glVertex3f(-1.0f,-1.0f, 1.0f);	// 四边形的左下顶点(前面)
		glVertex3f( 1.0f,-1.0f, 1.0f);	// 四边形的右下顶点(前面)

		glColor3f(1.0f,1.0f,0.0f);		// 颜色改成黄色
		glVertex3f( 1.0f,-1.0f,-1.0f);	// 四边形的右上顶点(后面)
		glVertex3f(-1.0f,-1.0f,-1.0f);	// 四边形的左上顶点(后面)
		glVertex3f(-1.0f, 1.0f,-1.0f);	// 四边形的左下顶点(后面)
		glVertex3f( 1.0f, 1.0f,-1.0f);	// 四边形的右下顶点(后面)

		glColor3f(0.0f,0.0f,1.0f);		// 颜色改成蓝色
		glVertex3f(-1.0f, 1.0f, 1.0f);	// 四边形的右上顶点(左面)
		glVertex3f(-1.0f, 1.0f,-1.0f);	// 四边形的左上顶点(左面)
		glVertex3f(-1.0f,-1.0f,-1.0f);	// 四边形的左下顶点(左面)
		glVertex3f(-1.0f,-1.0f, 1.0f);	// 四边形的右下顶点(左面)

		glColor3f(1.0f,0.0f,1.0f);		// 颜色改成紫罗兰色
		glVertex3f( 1.0f, 1.0f,-1.0f);	// 四边形的右上顶点(右面)
		glVertex3f( 1.0f, 1.0f, 1.0f);	// 四边形的左上顶点(右面)
		glVertex3f( 1.0f,-1.0f, 1.0f);	// 四边形的左下顶点(右面)
		glVertex3f( 1.0f,-1.0f,-1.0f);	// 四边形的右下顶点(右面)
	glEnd();	// 立方体绘制结束

	return TRUE;	//  一切 OK
}
示例效果:

2.纹理映射

纹理映射也就是纹理的贴片技术,某些情况下,为了使某个图形和真实的食物特别相似,就需要采用纹理贴片技术。比如,我们需要一个三维立体的西瓜,我们可以画一个球体,然后在这个球体上贴上一张西瓜的纹理(图片),就能得到相对逼真的三维立体西瓜。

1)在上例的基础上,添加如下两个函数:

/*******************************************************************************************************************************************
*AUX_RGBImageRec *LoadBMP()	
*功能:载入位图
*参数:无
*返回值:AUX_RGBImageRec
********************************************************************************************************************************************/
AUX_RGBImageRec *LoadBMP()
{
	FILE *File=NULL;		// 文件句柄
	File=fopen("Thistle.bmp","r");		// 尝试打开文件,只读方式
	if (File)				// 文件存在么?
	{
		fclose(File);			// 关闭句柄
		return auxDIBImageLoad(L"Thistle.bmp");	// 载入位图并返回指针
	}
	return NULL;		// 如果载入失败,返回 NULL
}

/*******************************************************************************************************************************************
*int LoadGLTextures()	
*功能:载入位图并转换成纹理
*参数:无
*返回值:无
********************************************************************************************************************************************/
int LoadGLTextures()								
{
	int Status=FALSE;	// 状态指示器
	AUX_RGBImageRec *TextureImage[1];	// 创建纹理的存储空间
	memset(TextureImage,0,sizeof(void *)*1);	// 将指针设为 NULL
	// 载入位图,检查有无错误,如果位图没找到则退出
	if (TextureImage[0]=LoadBMP())
	{
		Status=TRUE;	// 将 Status 设为 TRUE
		glGenTextures(1, &texture[0]);	// 创建纹理
		// 使用来自位图数据生成 的典型纹理
		glBindTexture(GL_TEXTURE_2D, texture[0]);
		// 生成纹理
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	// 线形滤波
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);	// 线形滤波
	}
	if (TextureImage[0])	// 纹理是否存在
	{
		if (TextureImage[0]->data)	// 纹理图像是否存在
		{
			free(TextureImage[0]->data);	// 释放纹理图像占用的内存
		}
		free(TextureImage[0]);	// 释放图像结构
	}
	return Status;	// 返回 Status
}

2)在初始化函数中添加载入纹理函数的初始化语句,如下所示:

/*******************************************************************************************************************************************
*int InitGL(GLvoid)		
*功能:初始化OpenGL绘图环境
*参数:无
*返回值:BOOL
********************************************************************************************************************************************/
int InitGL(GLvoid)		// 此处开始对OpenGL进行所有设置
{
	if (!LoadGLTextures())		// 调用纹理载入子例程
	{
		return FALSE;		// 如果未能载入,返回FALSE
	}
	glEnable(GL_TEXTURE_2D);	// 启用纹理映射
	glShadeModel(GL_SMOOTH);	// 启用阴影平滑
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);	// 黑色背景
	glClearDepth(1.0f);		// 设置深度缓存
	glEnable(GL_DEPTH_TEST);	// 启用深度测试
	glDepthFunc(GL_LEQUAL);	// 所作深度测试的类型
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);	// 告诉系统对透视进行修正
	return TRUE;	// 初始化 OK

}

3)为立方体添加纹理映射,所以在DrawGLScene(GLvoid)函数中添加纹理的处理函数,如下所示:

/*******************************************************************************************************************************************
*int DrawGLScene(GLvoid)		
*功能:绘图
*参数:无
*返回值:BOOL
********************************************************************************************************************************************/
int DrawGLScene(GLvoid)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// 清除屏幕和深度缓存
	glLoadIdentity();	// 重置当前的模型观察矩阵
	//添加绘图代码
	glTranslatef(.0f,0.0f,-5.0f);	// 并移入屏幕5个单位
	glRotatef(xrot,1.0f,0.0f,0.0f);	// 绕X轴旋转
	glRotatef(yrot,0.0f,1.0f,0.0f);	// 绕Y轴旋转
	glRotatef(zrot,0.0f,0.0f,1.0f);	// 绕Z轴旋转
	glBindTexture(GL_TEXTURE_2D, texture[0]);	// 选择纹理
	glBegin(GL_QUADS);		//  绘制立方体
		// 前面
		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);	// 纹理和四边形的左上
		// 后面
		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);	// 纹理和四边形的左下
		// 顶面
		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);	// 纹理和四边形的右上
		// 底面
		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);	// 纹理和四边形的右下
		// 右面
		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);	// 纹理和四边形的左下
		// 左面
		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();	// 立方体绘制结束
	xrot+=0.3f;		// X 轴旋转
	yrot+=0.2f;		// Y 轴旋转
	zrot+=0.4f;		// Z 轴旋转

	return TRUE;	//  一切 OK
}

4)准备一张.bmp格式的位图文件放在工程所在的目录下,然后编译运行,即可获得一个纹理贴片的立方体,如下所示:


  • 7
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
OpenGL是一种跨平台的图形库,用于渲染2D和3D图形纹理映射是一种将纹理图像映射到物体表面的技术。贝塞尔曲面是一种由贝塞尔曲线生成的曲面。 以下是一个简单的OpenGL纹理映射的代码示例: ```cpp #include <GL/glut.h> GLuint texture; // 纹理对象ID void init() { // 加载纹理图像 unsigned char image[] = { // 纹理图像数据 }; // 创建纹理对象 glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // 设置纹理参数 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 加载纹理图像数据 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image); } void display() { glClear(GL_COLOR_BUFFER_BIT); // 绑定纹理对象 glBindTexture(GL_TEXTURE_2D, texture); // 绘制物体并进行纹理映射 glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex2f(1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex2f(1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, 1.0f); glEnd(); glFlush(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutCreateWindow("OpenGL Texture Mapping"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; } ``` 贝塞尔曲面的代码示例比较复杂,这里给出一个简单的二次贝塞尔曲面的代码示例: ```cpp #include <GL/glut.h> void display() { glClear(GL_COLOR_BUFFER_BIT); // 设置贝塞尔曲面控制点 GLfloat controlPoints[3][3][3] = { {{-1.5, -1.5, 4.0}, {-0.5, -1.5, 2.0}, {0.5, -1.5, -1.0}}, {{-1.5, -0.5, 1.0}, {-0.5, -0.5, 3.0}, {0.5, -0.5, 0.0}}, {{-1.5, 0.5, 4.0}, {-0.5, 0.5, 0.0}, {0.5, 0.5, 3.0}} }; // 绘制贝塞尔曲面 glMap2f(GL_MAP2_VERTEX_3, 0.0, 1.0, 3, 3, 0.0, 1.0, 9, 3, &controlPoints[0][0][0]); glEnable(GL_MAP2_VERTEX_3); glMapGrid2f(20, 0.0, 1.0, 20, 0.0, 1.0); glEvalMesh2(GL_FILL, 0, 20, 0, 20); glFlush(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutCreateWindow("OpenGL Bezier Surface"); glutDisplayFunc(display); glutMainLoop(); return 0; } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值