学习如何使用纹理贴图,纹理贴图的一般步骤,纹理坐标的初体验.,设定步骤如下
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
米游 阅读(985)
评论(3) 编辑 收藏 引用 所属分类:
OpenGL/OSG