博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenGL纹理数据块
阅读量:4974 次
发布时间:2019-06-12

本文共 4209 字,大约阅读时间需要 14 分钟。

OpenGL纹理贴图渲染主要包含三步:

(1)在绘制前,加载OpenGL纹理资源

  a. 读取bmp宽高值和像素矩阵

  b. 调用glGenTextures获取纹理对象ID

  c. 调用glBindTextures绑定纹理对象ID,使得后续OpenGL指令使用该ID的纹理

  d. 调用glTexImage2D生成纹理

  e. 设置一些OpenGL处理纹理的参数

BOOL LoadGLTextures()			// 载入位图并转换成纹理{	int Status=FALSE;            	// 状态指示器	int w = 0;	int h = 0;	unsigned char* pImage=NULL;	if (ReadBMP("Debug/Data/tree.bmp", pImage, w, h))	{		Status=TRUE;		// 将 Status 设为 TRUE		glGenTextures(1, &texture[0]);	// 创建纹理		// 使用来自位图数据生成 的典型纹理		glBindTexture(GL_TEXTURE_2D, texture[0]);		// 生成纹理		glTexImage2D(GL_TEXTURE_2D, 0, 3, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, pImage/*TextureImage[0]->data*/);		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);	// 线形滤波		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);	// 线形滤波	}	if (pImage) free(pImage);	return Status;				// 返回 Status}

(2)启用纹理映射

glEnable(GL_TEXTURE_2D);			// 启用纹理映射

(3)场景绘制

  a. 绑定一个纹理对象ID,使得后续OpenGL指令使用该ID的纹理

  b. 设置顶点纹理坐标

int DrawGLScene(GLvoid){	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// 清除屏幕和深度缓存	glLoadIdentity();		// 重置当前的模型观察矩阵	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();															return TRUE;}

绘制的结果如下图(立方体):

++++

读取BMP像素要注意的是():

(1) 贴图的长宽应相等,且为2的n次方[n>0&&n<10]

(2) 去除BMP文件中每行末尾要求的4字节对齐的无效像素(保持数据紧密)

(3) 将每个像素按RGB顺序存放,而BMP为BGR存放;因此,需要交换R和B的值

代码如下(以24位BMP为例):

bool ReadBMP(CHAR *Filename, unsigned char*& pImage, int& w, int& h){	FILE* pBmpFile = fopen(Filename, "rb");	if (!pBmpFile) return false;	BITMAPFILEHEADER filehdr;	BITMAPINFOHEADER infohdr;	fread(&filehdr, 1, sizeof(filehdr), pBmpFile);     	fread(&infohdr, 1, sizeof(infohdr), pBmpFile);    	unsigned tmpImaLength = filehdr.bfSize - filehdr.bfOffBits;	unsigned char* pTmpIma = new unsigned char[tmpImaLength];	fseek(pBmpFile, filehdr.bfOffBits, SEEK_SET);   	fread(pTmpIma, 1, tmpImaLength, pBmpFile);	w = infohdr.biWidth;	h = infohdr.biHeight;	unsigned __int64 imageLength = (unsigned __int64)3*w*h;	pImage = new unsigned char[imageLength];	unsigned idx = 0;	unsigned bmpIdx = 0;	for (long i=0; i
0) bmpIdx += (4-lineLeftByte); } delete [] pTmpIma; fclose(pBmpFile); return true;}

为了避免这些麻烦,可以使用OpenGL提供的auxDIBImageLoadA来读BMP图片。

AUX_RGBImageRec *TextureImage[1];	// 创建纹理的存储空间memset(TextureImage,0,sizeof(void *)*1);TextureImage[0] = auxDIBImageLoadA(Filename);

生成纹理之后,记得要把TexureImage[0]->data和TexureImage[0]的堆内存free掉!

转载于:https://www.cnblogs.com/kekec/archive/2011/12/12/2285373.html

你可能感兴趣的文章
DS-5/RVDS4.0变量初始化错误
查看>>
簡單SQL存儲過程實例
查看>>
css basic
查看>>
GCC编译警告和错误
查看>>
Spring 笔记
查看>>
变量定义规范
查看>>
死锁的形成以及处理
查看>>
Spring Boot的三种启动方式
查看>>
转:storm中一个Bolt发emit多次相同类型消息
查看>>
MySql行列转换方法自我总结
查看>>
查询归档量
查看>>
搜索引擎营销入门
查看>>
#leetcode刷题之路25- k个一组翻转链表
查看>>
1.linux源码安装nginx
查看>>
GDB之调试器用法
查看>>
七牛云简单实用-uploadManager.put(..)抛出异常
查看>>
算法经典文章收藏
查看>>
java处理大文本方案
查看>>
定时任务crone表达式demo
查看>>
iOS 改变UILabel部分颜色
查看>>