zoukankan      html  css  js  c++  java
  • OpenGL纹理数据块

    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像素要注意的是(关于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<infohdr.biHeight; i++)
    	{
    		for (long j=0; j<infohdr.biWidth; j++)
    		{
    			pImage[idx]   = pTmpIma[bmpIdx+2];
    			pImage[idx+1] = pTmpIma[bmpIdx+1];
    			pImage[idx+2] = pTmpIma[bmpIdx];
    			bmpIdx += 3;
    			idx    += 3;
    		}
    		long lineLeftByte = (3*infohdr.biWidth)%4;
    		if (lineLeftByte>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掉!

  • 相关阅读:
    Kali视频学习21-25
    20159315《网络攻防实践》第六周学习总结
    Kali视频学习16-20
    20159315《网络攻防实践》第五周学习总结
    一个PE文件的逆向分析
    一个好玩的CTF题
    对于安卓锁屏中知识点小结
    安卓系统安全措施
    安卓防逆向、防动态分析、渗透测试及加固
    安卓组件漏洞防护注意事项
  • 原文地址:https://www.cnblogs.com/kekec/p/2285373.html
Copyright © 2011-2022 走看看