您的位置:首页 > 运维架构

OpenGL学习笔记之加载纹理

2017-08-30 09:12 477 查看

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_
ea68
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;
}


//运行效果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: