OpenGL学习笔记之加载纹理

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<<"文件不存在!"<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();

}

纹理贴图坐标系

OpenGL学习笔记之加载纹理_第1张图片


源代码

//工具

#pragma once

#include 
#include 
#include 
#include 

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<std::endl;//输出命令个数

    for(int i = 0; i < argc; ++i)//输出命令内容
    {
        std::cout<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 = "<" ,y = "<std::endl;
    CGameManager::GetInstance().MouseFunc(button,state,x,y);
}
//鼠标按着拖动
void MotionFunc(int x,int y)
{
    //x,y  鼠标的像素点坐标(以窗口的左上角为原点的坐标系)
    std::cout<<"鼠标按着拖动的坐标:x = "<" ,y = "<std::endl;
}
//鼠标移动
void PassiveMotionFunc(int x,int y)
{
    //x,y  鼠标的像素点坐标(以窗口的左上角为原点的坐标系)
    std::cout<<"鼠标移动的坐标:x = "<" ,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<<"鼠标左键按下"<if(state == 1)
        {
            std::cout<<"鼠标左键抬起"<if(button == 1)
    {
        if(state == 0)
        {
            std::cout<<"鼠标中键按下"<if(state == 1)
        {
            std::cout<<"鼠标中键抬起"<if(button == 2)
    {
        if(state == 0)
        {
            std::cout<<"鼠标右键按下"<if(state == 1)
        {
            std::cout<<"鼠标右键抬起"<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<<"文件不存在!"<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;
}

//运行效果
OpenGL学习笔记之加载纹理_第2张图片

你可能感兴趣的:(OpenGL学习笔记)