OpenGL学习笔记之加载纹理

来源:互联网 发布:ubuntu和windows比较 编辑:程序博客网 时间:2024/05/17 05:58

OpenGL学习笔记之加载纹理

纹理贴图步骤

1、在主函数打开纹理贴图的开关glEnable(GL_TEXTURE_2D);2、加载位图文件struct BMP{    int iWidth;//图片像素宽    int iHeight;//图片像素高    char* pColor;//图片颜色首地址    BMP(int width = 0,int height = 0,char* color = NULL):iWidth(width),iHeight(height),pColor(color)    {    }};BMP CGameManager::LoadBmp(const char* pFileName){    FILE* pFile;//文件指针    fopen_s(&pFile,pFileName,"rb");//打开文件名为pFileName的文件    if(pFile == NULL)        std::cout<<"文件不存在!"<<std::endl;    fseek(pFile,0,SEEK_END);//让文件指针偏向文件尾    int iFileLength = ftell(pFile);//得到文件的大小    rewind(pFile);//让文件指针指向文件头    pBmpFileHeader = (BITMAPFILEHEADER*)new char[iFileLength];    fread(pBmpFileHeader,1,iFileLength,pFile);//将文件读取到pBmpFileHeader指向的内存中    fclose(pFile);//关闭文件    if(pBmpFileHeader->bfType != 'MB')//如果文件的类型的不是位图文件(MB--代表位图)    {        delete [] pBmpFileHeader;//释放内存        return BMP(0,0,0);//返回空位图    }    BMP bmp;//定义一个BMP结构体的对象bmp    bmp.iWidth = ((BITMAPINFOHEADER*)(pBmpFileHeader + 1))->biWidth;    bmp.iHeight = ((BITMAPINFOHEADER*)(pBmpFileHeader + 1))->biHeight;    bmp.pColor = (char*)pBmpFileHeader + pBmpFileHeader->bfOffBits;//颜色的偏移量    return bmp;}3、创建纹理GLuint CGameManager::LoadTexture(const char* pFileName)//加载纹理{    GLuint TextureID;//    glGenTextures(1,&TextureID);//在显存创建一个空间,并得到空间编号    glBindTexture(GL_TEXTURE_2D,TextureID);//将创建的空间与TextureID号绑定    BMP bmp = LoadBmp(pFileName);//加载位图    glTexParameterf(GL_TEXTURE_2D/*二维纹理*/,GL_TEXTURE_MIN_FILTER/*缩小*/,GL_LINEAR/*线性采样*/);//设置纹理参数    glTexParameterf(GL_TEXTURE_2D/*二维纹理*/,GL_TEXTURE_MAG_FILTER/*放大*/,GL_LINEAR/*线性采样*/);//设置纹理参数    //把图片处理为纹理    glTexImage2D(GL_TEXTURE_2D/*二维纹理*/,0/*表示不创建多级渐进纹理*/,GL_RGB/*RGB模式*/,        bmp.iWidth/*纹理像素宽*/,bmp.iHeight/*纹理像素高*/,0/*不设置纹理边界*/,        GL_BGR_EXT/*表示纹理像素的格式为B、G、R的排列*/,GL_UNSIGNED_BYTE,bmp.pColor/*纹理像素颜色的起始地址*/);    return TextureID;}4、使用纹理void CGameManager::Darw(){    glBindTexture(GL_TEXTURE_2D,TextureID);//将TextureID所绑定的纹理作为当前绘图纹理    glBegin(GL_TRIANGLES);    {        glTexCoord2f(0,1);//纹理贴图坐标(使用纹理贴图坐标系)        glVertex2f(g_vector2D.fX,g_vector2D.fY);        glTexCoord2f(1,1);        glVertex2f(g_vector2D.fX+0.4f,g_vector2D.fY);        glTexCoord2f(0.5,0);        glVertex2f(g_vector2D.fX+0.2f,g_vector2D.fY-0.4f);    }    glEnd();}

纹理贴图坐标系

这里写图片描述


源代码

//工具

#pragma once#include <gl/glew.h>#include <gl/glut.h>#include <iostream>#include <windows.h>const int ISCREENWIDTH = 650;const int ISCREENHEIGHT = 650;struct Vector2D{    float fX;    float fY;};struct BMP{    int iWidth;    int iHeight;    char* pColor;    BMP(int width = 0,int height = 0,char* color = NULL):iWidth(width),iHeight(height),pColor(color)    {    }};

//主函数

#include "head.h"//第一个参数是命令的个数,第二个参数是命令内容int main(int argc,char** argv){    std::cout<<argc<<std::endl;//输出命令个数    for(int i = 0; i < argc; ++i)//输出命令内容    {        std::cout<<argv[i]<<std::endl;    }    glutInit(&argc,argv);//初始化glut库(创建窗口需要)    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);//初始化显示模式 GLUT_RGBA 颜色 GLUT_DOUBLE 双缓冲    int iScreenWidth = glutGet(GLUT_SCREEN_WIDTH);    int iScreenHeight = glutGet(GLUT_SCREEN_HEIGHT);    glutInitWindowPosition((iScreenHeight - ISCREENWIDTH)/2,(iScreenHeight - ISCREENHEIGHT)/2 );//初始化我们创建的窗口在屏幕左上角的位置    glutInitWindowSize(ISCREENWIDTH,ISCREENHEIGHT);//初始化创建窗口的宽高    int iWindowID = glutCreateWindow("OpenGL");//创建窗口,并返回窗口的ID,传窗口的标题    glutDisplayFunc(DisplayFunc);//屏幕显示的回调函数    glutIdleFunc(IdleFunc);//闲置时回调函数(当没有消息时调用)    glutKeyboardFunc(KeyboardFunc);//数字、字母键的按键检测的回调函数    glutSpecialFunc(SpecialFunc);//特殊按键检测(F1~F12,控制键)    glutMouseFunc(MouseFunc);//鼠标检测    glutMotionFunc(MotionFunc);//鼠标按着拖动检测    glutPassiveMotionFunc(PassiveMotionFunc);//鼠标移动检测    glEnable(GL_LINE_STIPPLE);//开启画虚线的模式    glEnable(GL_TEXTURE_2D);//开启贴图开关    glClearColor(0.0f,0.6f,0.6f,1.0f);//指定屏幕背景色,最后参数为透明度    CGameManager::GetInstance().Init();    glutMainLoop();//消息主循环    //glutDestroyWindow(iWindowID);//销毁窗口    return 1;}

//主函数需要的函数

#include "Tool.h"#include "GameManager.h"void DisplayFunc();//显示函数void IdleFunc();//闲置时调用的函数void KeyboardFunc(unsigned char Key,int x,int y);//数字、字母键按键检测void SpecialFunc(int Key,int x,int y);//F1~F12、控制键检测void MouseFunc(int button,int state,int x,int y);//鼠标检测void MotionFunc(int x,int y);//鼠标按着拖动void PassiveMotionFunc(int x,int y);//鼠标移动
#include "head.h"Vector2D g_vector2D = {-0.2f,0.2f};void DisplayFunc(){    glClear(GL_COLOR_BUFFER_BIT);//用指定的颜色清屏    CGameManager::GetInstance().Darw();    glFlush();//提交绘图命令    glutSwapBuffers();//交换前台缓冲与后台缓冲(GLUT_DOUBLE双缓冲模式需要)}//闲置时调用的函数void IdleFunc(){    CGameManager::GetInstance().Run();    glutPostRedisplay();//重新绘制(即调用DisplayFunc()函数)}//数字、字母键按键检测void KeyboardFunc(unsigned char Key,int x,int y){    CGameManager::GetInstance().KeyboardFunc(Key,x,y);}//F1~F12、控制键检测void SpecialFunc(int Key,int x,int y){    CGameManager::GetInstance().SpecialFunc(Key,x,y);}//鼠标检测void MouseFunc(int button,int state,int x,int y){    //button  鼠标按键 0 -- 左键    1 -- 中键   2 -- 右键    //state  鼠标状态  0 -- 按下  1 -- 抬起    //x,y  鼠标的像素点坐标(以窗口的左上角为原点的坐标系)    std::cout<<"鼠标的坐标:x = "<<x<<" ,y = "<<y<<std::endl;    CGameManager::GetInstance().MouseFunc(button,state,x,y);}//鼠标按着拖动void MotionFunc(int x,int y){    //x,y  鼠标的像素点坐标(以窗口的左上角为原点的坐标系)    std::cout<<"鼠标按着拖动的坐标:x = "<<x<<" ,y = "<<y<<std::endl;}//鼠标移动void PassiveMotionFunc(int x,int y){    //x,y  鼠标的像素点坐标(以窗口的左上角为原点的坐标系)    std::cout<<"鼠标移动的坐标:x = "<<x<<" ,y = "<<y<<std::endl;}

//游戏管理器

#pragma once#include "Tool.h"class CGameManager{    GLuint TextureID;//纹理编号    Vector2D g_vector2D;    BITMAPFILEHEADER* pBmpFileHeader;//指向位图文件的指针    CGameManager();    CGameManager(const CGameManager& that);public:    static CGameManager& GetInstance();    void Init();    void Darw();    void Run();    void End();    void KeyboardFunc(unsigned char Key,int x,int y);    void SpecialFunc(int Key,int x,int y);    void MouseFunc(int button,int state,int x,int y);    GLuint LoadTexture(const char* pFileName);//加载纹理    BMP LoadBmp(const char* pFileName);//加载位图};
#include "GameManager.h"CGameManager::CGameManager(){}CGameManager::CGameManager(const CGameManager& that){}CGameManager& CGameManager::GetInstance(){    static CGameManager gameManager;    return gameManager;}void CGameManager::Init(){    TextureID = LoadTexture("Texture.bmp");}void CGameManager::Darw(){    glBindTexture(GL_TEXTURE_2D,TextureID);//将TextureID所绑定的纹理作为当前绘图纹理    glBegin(GL_TRIANGLES);    {        glTexCoord2f(0,1);//纹理贴图坐标(使用纹理贴图坐标系)        glVertex2f(g_vector2D.fX,g_vector2D.fY);        glTexCoord2f(1,1);        glVertex2f(g_vector2D.fX+0.4f,g_vector2D.fY);        glTexCoord2f(0.5,0);        glVertex2f(g_vector2D.fX+0.2f,g_vector2D.fY-0.4f);    }    glEnd();}void CGameManager::Run(){}void CGameManager::End(){}void CGameManager::KeyboardFunc(unsigned char Key,int x,int y){    if(Key == 'w' || Key == 'W')    {        if(g_vector2D.fY < 1.0f)//界限判定            g_vector2D.fY += 0.05f;    }    if(Key == 's' || Key == 'S')    {        if(g_vector2D.fY - 0.4f > -1.0f)//界限判定            g_vector2D.fY -= 0.05f;    }    if(Key == 'a' || Key == 'A')    {        if(g_vector2D.fX > -1.0f)//界限判定            g_vector2D.fX -= 0.05f;    }    if(Key == 'd' || Key == 'D')    {        if(g_vector2D.fX + 0.4f< 1.0f)//界限判定            g_vector2D.fX += 0.05f;    }}void CGameManager::SpecialFunc(int Key,int x,int y){    if(Key == GLUT_KEY_UP)    {        if(g_vector2D.fY < 1.0f)//界限判定            g_vector2D.fY += 0.05f;    }    if(Key == GLUT_KEY_DOWN)    {        if(g_vector2D.fY - 0.4f > -1.0f)//界限判定            g_vector2D.fY -= 0.05f;    }    if(Key == GLUT_KEY_LEFT)    {        if(g_vector2D.fX > -1.0f)//界限判定            g_vector2D.fX -= 0.05f;    }    if(Key == GLUT_KEY_RIGHT)    {        if(g_vector2D.fX + 0.4f< 1.0f)//界限判定            g_vector2D.fX += 0.05f;    }}void CGameManager::MouseFunc(int button,int state,int x,int y){    if(button == 0)    {        if(state == 0)        {            std::cout<<"鼠标左键按下"<<std::endl;        }        if(state == 1)        {            std::cout<<"鼠标左键抬起"<<std::endl;        }    }    if(button == 1)    {        if(state == 0)        {            std::cout<<"鼠标中键按下"<<std::endl;        }        if(state == 1)        {            std::cout<<"鼠标中键抬起"<<std::endl;        }    }    if(button == 2)    {        if(state == 0)        {            std::cout<<"鼠标右键按下"<<std::endl;        }        if(state == 1)        {            std::cout<<"鼠标右键抬起"<<std::endl;        }    }}GLuint CGameManager::LoadTexture(const char* pFileName)//加载纹理{    GLuint TextureID;//    glGenTextures(1,&TextureID);//在显存创建一个空间,并得到空间编号    glBindTexture(GL_TEXTURE_2D,TextureID);//将创建的空间与TextureID号绑定    BMP bmp = LoadBmp(pFileName);//加载位图    glTexParameterf(GL_TEXTURE_2D/*二维纹理*/,GL_TEXTURE_MIN_FILTER/*缩小*/,GL_LINEAR/*线性采样*/);//设置纹理参数    glTexParameterf(GL_TEXTURE_2D/*二维纹理*/,GL_TEXTURE_MAG_FILTER/*放大*/,GL_LINEAR/*线性采样*/);//设置纹理参数    //把图片处理为纹理    glTexImage2D(GL_TEXTURE_2D/*二维纹理*/,0/*表示不创建多级渐进纹理*/,GL_RGB/*RGB模式*/,        bmp.iWidth/*纹理像素宽*/,bmp.iHeight/*纹理像素高*/,0/*不设置纹理边界*/,        GL_BGR_EXT/*表示纹理像素的格式为B、G、R的排列*/,GL_UNSIGNED_BYTE,bmp.pColor/*纹理像素颜色的起始地址*/);    return TextureID;}BMP CGameManager::LoadBmp(const char* pFileName){    FILE* pFile;//文件指针    fopen_s(&pFile,pFileName,"rb");//打开文件名为pFileName的文件    if(pFile == NULL)        std::cout<<"文件不存在!"<<std::endl;    fseek(pFile,0,SEEK_END);//让文件指针偏向文件尾    int iFileLength = ftell(pFile);//得到文件的大小    rewind(pFile);//让文件指针指向文件头    pBmpFileHeader = (BITMAPFILEHEADER*)new char[iFileLength];    fread(pBmpFileHeader,1,iFileLength,pFile);//将文件读取到pBmpFileHeader指向的内存中    fclose(pFile);//关闭文件    if(pBmpFileHeader->bfType != 'MB')//如果文件的类型的不是位图文件(MB--代表位图)    {        delete [] pBmpFileHeader;//释放内存        return BMP(0,0,0);//返回空位图    }    BMP bmp;//定义一个BMP结构体的对象bmp    bmp.iWidth = ((BITMAPINFOHEADER*)(pBmpFileHeader + 1))->biWidth;    bmp.iHeight = ((BITMAPINFOHEADER*)(pBmpFileHeader + 1))->biHeight;    bmp.pColor = (char*)pBmpFileHeader + pBmpFileHeader->bfOffBits;//颜色的偏移量    return bmp;}

//运行效果
这里写图片描述

原创粉丝点击