学习如何使用纹理贴图,纹理贴图的一般步骤,纹理坐标的初体验.,设定步骤如下
glGenTextures(1,&texnum); //创建一个纹理
glBindTexture(GL_TEXTURE_2D,texnum); //指定一个纹理
//设置纹理的一些数据等...
.....
...
glEnable(GL_TEXTURE_2D); //启用纹理功能
选择一个纹理,提供纹理坐标
glBindTexture(GL_TEXTURE_2D,texnum);
glTexCoord2f(x,y) //设定每个点的纹理坐标
一张二维纹理贴图,相当于一个矩形数据..
最左边对应 x-->0.0,最右边对应 x-->1.0
最下边对应 y->0.0 最上边对应 y-->1.0
其次对于一张bmp图片,应为glut中并不提供读取图像数据的方法.而纹理贴图中图像的数据必须得自己
创建函数从文件中读取出来 最后绑定在纹理上..
这里我将使用的是win API 的方法读取一张bmp文件
WINUSERAPI HANDLE WINAPI LoadImage( HINSTANCE, LPCWSTR, UINT,int, int, UINT);
参数分别表示如下:
HINSTANCE---------包含所需要图片的实例的句柄。
LPCSTR--------------图片所在路径及文件名。
UINT-------------------图片类型。
int-----------------------图片宽度。
int-----------------------图片高度。
UINT-------------------load flags
HINSTANCE ---将使用GetModuleHandle(NULL) 获得..就是获得一个应用程序的句柄,NULL代表当前这个程序
获得了位图的句柄之后 使用以下函数获得图像数据
int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
使用以下代码时候,需要在lesson_1中的openglglut.h 添加一个函数声明: void InitTexture(void);

code

#include "openglglut.h"


/**//**
** 纹理映射的学习
** 将一张bmp格式的图片以纹理贴图的方式,贴在正方体的6个面
*/

GLfloat xRot=0; /**//** 正方体绕x轴旋转角度*/

GLfloat yRot=0; /**//** 正方体绕y轴旋转角度*/

GLfloat zRot=0; /**//** 正方体绕z轴旋转角度*/

static GLuint texnum; /**//** 定义存储纹理*/

/**//** 这是一个通过WIN API 载入一张bmp格式图片的方法*/
bool LoadBmpTexture(LPTSTR filename,GLuint& texid)


{

HBITMAP bBmp; /**//** 位图文件的句柄*/

BITMAP bmp; /**//** 位图的结构*/

/**//** 通过API LoadImage 读入bmp文件,获得句柄*/
bBmp=(HBITMAP)LoadImage(GetModuleHandle(NULL),filename,IMAGE_BITMAP,0,0,
LR_CREATEDIBSECTION | LR_LOADFROMFILE);

if(!bBmp)
return false;

/**//** 获得图像数据对象*/
GetObject(bBmp,sizeof(bmp),&bmp);


/**//*
glPixelStroei(GLenum pname,GLint param)
pname: GL_PACK_ALIGNMENT 将影响opengl如何将像素数据存入内存(应该是说存储结构).
GL_UNPACK_ALIGNMENT 将影响opengl读取内存中的像素数据后的存储结构.
param: 为内存中每行像素的起始位置指定校准需求,有四种值
1: byte-alignment
2: rows aligned to even-numbered bytes
4: word-alignment
8: rows start on double-word boundaries

默认值是:4
*/




glPixelStorei(GL_UNPACK_ALIGNMENT,4); /**//** ? */


glGenTextures(1,&texid); /**//** 创建一个纹理*/

glBindTexture(GL_TEXTURE_2D,texid); /**//** 为它指定一个纹理*/


glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); /**//** 线性滤波 */

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); /**//** 线性滤波 */

/**//**
* glTexImage2D的参数比较复杂,
使用 GL_BGR_EXT的原因是: winapi里 bmp存储的格式是BGR 与opengl中RBG 需要做个转换
*/

glTexImage2D(GL_TEXTURE_2D,0,3,bmp.bmWidth,bmp.bmHeight

,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,bmp.bmBits); /**//** 生成纹理*/


DeleteObject(bBmp); /**//** 删除对象,释放内存*/

return true;
}
int main(int argc,char** argv)


{

createWindow("opengl lesson_6",&argc,argv); /**//** 初始化并创建窗口*/


glutDisplayFunc(glutDisplay); /**//** 注册重绘函数*/

glutIdleFunc(glutIdle); /**//** 注册空闲回调函数*/

glutReshapeFunc(glutResize); /**//** 注册窗口调整函数*/

glutSpecialFunc(glutSpecial); /**//** 注册特殊按键窗口*/

glutKeyboardFunc(glutKeyboard); /**//** 注册键盘处理函数*/


InitTexture(); /**//** 初始化启用纹理映射并加载纹理*/

InitOpenGL(); /**//** 初始化opengl*/

glutMainLoop(); /**//** 仿真循环*/
}
void InitTexture(void)


{

/**//** 读入工程目录下data文件中的bmp文件*/
if(!LoadBmpTexture(L"..\\Data\\NeHe.bmp",texnum))

{
printf("load texture error!\n");
exit(0);
}

/**//** 若载入纹理成功 则启用纹理映射*/
glEnable(GL_TEXTURE_2D);
}

void glutDisplay(void) /**//** 重绘函数*/


{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);/**//** 清除颜色缓存和深度缓存*/

glLoadIdentity(); /**//** 初始化当前矩阵为单位矩阵*/



glTranslatef(0.0,0.0,-6.0); /**//** 往左移动和往屏幕内部移动,绘制正方体*/

glRotatef(xRot,1.0,0.0,0.0); /**//** 正方体绕x轴旋转xRot角度*/

glRotatef(yRot,0.0,1.0,0.0); /**//** 正方体绕y轴旋转yRot角度*/

glRotatef(zRot,0.0,0.0,1.0); /**//** 正方体绕z轴旋转zRot角度*/

glBindTexture(GL_TEXTURE_2D,texnum); /**//** 选择一个纹理*/

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();
glutSwapBuffers();

}

void glutIdle(void) /**//** 回调函数*/


{

xRot+=0.3; /**//** 绕x轴旋转角度递增*/

yRot+=0.2; /**//** 绕y轴旋转角度递增*/

zRot+=0.4f; /**//** 绕z轴旋转角度递增*/

glutPostRedisplay(); /**//** 使得函数完成后进行窗口重绘*/
}

void glutKeyboard(unsigned char key,int x,int y)


{
switch(key)

{

case 27: /**//** Esc按键按下后退出程序 */
exit(0);
break;
default:
break;
}
}





最终结果显示为:

末尾总结:
使用纹理的步骤 应当如下:
1.创建纹理对象,并为它指定一个纹理
2. 确定纹理是如何应用到每个像素上
3.启用纹理贴图功能
4.绘制场景,提供纹理和几何坐标
其次,如何使用winapi读取bmp图像数据.在以后的学习中可能还会遇到各种图像贴图的读取.
对于各种格式的文件很有可能都将要创建一种方法去读取数据,才能最终应用到纹理上?
posted on 2009-07-17 20:46
米游 阅读(1002)
评论(3) 编辑 收藏 引用 所属分类:
OpenGL/OSG