opengl学习 nehe opengl lesson_6

opengl学习 nehe opengl lesson_6


学习如何使用纹理贴图,纹理贴图的一般步骤,纹理坐标的初体验.,设定步骤如下

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.0f0.0f); glVertex3f(-1.0f-1.0f1.0f); // 纹理和四边形的左下
        glTexCoord2f(1.0f0.0f); glVertex3f( 1.0f-1.0f1.0f); // 纹理和四边形的右下
        glTexCoord2f(1.0f1.0f); glVertex3f( 1.0f1.0f1.0f); // 纹理和四边形的右上
        glTexCoord2f(0.0f1.0f); glVertex3f(-1.0f1.0f1.0f); // 纹理和四边形的左上
        
// 后面
        glTexCoord2f(1.0f0.0f); glVertex3f(-1.0f-1.0f-1.0f); // 纹理和四边形的右下
        glTexCoord2f(1.0f1.0f); glVertex3f(-1.0f1.0f-1.0f); // 纹理和四边形的右上
        glTexCoord2f(0.0f1.0f); glVertex3f( 1.0f1.0f-1.0f); // 纹理和四边形的左上
        glTexCoord2f(0.0f0.0f); glVertex3f( 1.0f-1.0f-1.0f); // 纹理和四边形的左下
        
// 顶面
        glTexCoord2f(0.0f1.0f); glVertex3f(-1.0f1.0f-1.0f); // 纹理和四边形的左上
        glTexCoord2f(0.0f0.0f); glVertex3f(-1.0f1.0f1.0f); // 纹理和四边形的左下
        glTexCoord2f(1.0f0.0f); glVertex3f( 1.0f1.0f1.0f); // 纹理和四边形的右下
        glTexCoord2f(1.0f1.0f); glVertex3f( 1.0f1.0f-1.0f); // 纹理和四边形的右上
        
// 底面
        glTexCoord2f(1.0f1.0f); glVertex3f(-1.0f-1.0f-1.0f); // 纹理和四边形的右上
        glTexCoord2f(0.0f1.0f); glVertex3f( 1.0f-1.0f-1.0f); // 纹理和四边形的左上
        glTexCoord2f(0.0f0.0f); glVertex3f( 1.0f-1.0f1.0f); // 纹理和四边形的左下
        glTexCoord2f(1.0f0.0f); glVertex3f(-1.0f-1.0f1.0f); // 纹理和四边形的右下
        
// 右面
        glTexCoord2f(1.0f0.0f); glVertex3f( 1.0f-1.0f-1.0f); // 纹理和四边形的右下
        glTexCoord2f(1.0f1.0f); glVertex3f( 1.0f1.0f-1.0f); // 纹理和四边形的右上
        glTexCoord2f(0.0f1.0f); glVertex3f( 1.0f1.0f1.0f); // 纹理和四边形的左上
        glTexCoord2f(0.0f0.0f); glVertex3f( 1.0f-1.0f1.0f); // 纹理和四边形的左下
        
// 左面
        glTexCoord2f(0.0f0.0f); glVertex3f(-1.0f-1.0f-1.0f); // 纹理和四边形的左下
        glTexCoord2f(1.0f0.0f); glVertex3f(-1.0f-1.0f1.0f); // 纹理和四边形的右下
        glTexCoord2f(1.0f1.0f); glVertex3f(-1.0f1.0f1.0f); // 纹理和四边形的右上
        glTexCoord2f(0.0f1.0f); glVertex3f(-1.0f1.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;
    }

}






最终结果显示为:

opengl学习 nehe opengl lesson_6_第1张图片

末尾总结:

使用纹理的步骤 应当如下:
1.创建纹理对象,并为它指定一个纹理
2. 确定纹理是如何应用到每个像素上
3.启用纹理贴图功能
4.绘制场景,提供纹理和几何坐标

其次,如何使用winapi读取bmp图像数据.在以后的学习中可能还会遇到各种图像贴图的读取.
对于各种格式的文件很有可能都将要创建一种方法去读取数据,才能最终应用到纹理上?

你可能感兴趣的:(opengl学习 nehe opengl lesson_6)