bmp.h
class BMP
{
private:
unsigned char * pBitmapData; //纹理对象
public:
int nRows, nCols; //bmp图像的尺寸
unsigned int texture_id; //纹理ID
BMP(){};
~BMP();
bool readBMPFile(char *fileName); //读取bmp图像
void setTexture(); //设置纹理
};
//析构,释放内存
BMP::~BMP()
{
delete []pBitmapData;
nRows = nCols = 0;
}
//读取位图
//由4部分组成:位图文件头、位图信息头、彩色表、图像数据阵列字节
bool BMP::readBMPFile(char *fileName)
{
FILE * fp;
BITMAPFILEHEADER bmpFH;
BITMAPINFOHEADER bmpIH;
unsigned char temp;
// 读取二进制文件
fp = fopen( fileName, "rb" );
if( fp == NULL )
return( false );
// 位图文件头
fread( ( void * )&bmpFH, sizeof( BITMAPFILEHEADER ), 1, fp );
//文件的类型
if( bmpFH.bfType != 0x4D42 )
{
fclose( fp );
return( false );
}
// 位图信息头
fread( ( void * )&bmpIH, sizeof( BITMAPINFOHEADER ), 1, fp );
// 移动到图像开始的位置
fseek( fp, bmpFH.bfOffBits, SEEK_SET );
// 位图字节数量
bmpIH.biSizeImage = bmpIH.biHeight * bmpIH.biWidth * ( bmpIH.biBitCount / 8 );
// 分配内存
pBitmapData = new unsigned char[ bmpIH.biSizeImage ];
if( pBitmapData == NULL )
{
fclose( fp );
return( false );
}
// 读取图像数据,每次1字节,共biSizeImage次
fread( ( void * )pBitmapData, 1, bmpIH.biSizeImage, fp );
if( pBitmapData == NULL )
{
fclose( fp );
return( false );
}
for( int c = 0; c < bmpIH.biSizeImage; c += 3 )
{
// 交换红、蓝字节
temp = pBitmapData[ c ];
pBitmapData[ c ] = pBitmapData[ c + 2 ];
pBitmapData[ c + 2 ] = temp;
}
fclose( fp );
nCols = bmpIH.biWidth;
nRows = bmpIH.biHeight;
return( true );
}
//设置纹理
void BMP::setTexture()
{
glGenTextures( 1, &texture_id );
//绑定纹理对象
glBindTexture( GL_TEXTURE_2D, texture_id );
//设置缩小放大的纹理过滤器
//进行纹理放大过滤
//GL_LINEAR:使用距离当前渲染像素中心最近的4个纹素的加权平均值
//GL_NEAREST:使用距离当前渲染像素中心最近的纹素
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
//进行纹理缩小过滤
//使用双线性过滤对最接近当前多边形解析度的两个层级贴图层进行采样,
//然后用这两个值进行线性插值,又叫做三线性过滤---必须显卡支持才会显示出纹理
//glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
//为纹理对象指定纹理
glTexImage2D( GL_TEXTURE_2D, //二维纹理
0, //贴图纹理的精细度等级
GL_RGB, //纹理是以怎样的基本内部格式储存到显示卡内存中
nRows, //纹理贴图的宽,2的幂
nCols, //纹理贴图的高
0, //当前纹理无边缘
GL_RGB, //pBitmapData数组中的图像数据的格式
GL_UNSIGNED_BYTE, //纹理图像数据类型
pBitmapData ); //指针,指向直接生成或从现有文件中读取的图像
}
main.cpp
#include <windows.h>
#include <gl/Gl.h>
#include <gl/Glu.h>
#include <gl/glut.h>
#include "stdio.h"
#include "stdlib.h"
#include "bmp.h"
#pragma comment(lib, "glut.lib")
const int windowWidth = 800;
const int windowHeight = 600;
BMP bmp;
void render()
{
//清除屏幕和深度缓存
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//再次绑定纹理对象
glBindTexture( GL_TEXTURE_2D, bmp.texture_id );
glBegin( GL_QUADS );
//指定纹理坐标
glTexCoord2f( 0.0, 0.0 ); glVertex3f( -4, -4, 0 ); //左下
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -4, 4, 0 ); //右下
glTexCoord2f( 1.0, 1.0 ); glVertex3f( 4, 4, 0 ); //右上
glTexCoord2f( 1.0, 0.0 ); glVertex3f( 4, -4, 0 ); //左上
/*第2种
glTexCoord2f( 0.0, 0.0 ); glVertex2f( 300, 400 ); //左下
glTexCoord2f( 1.0, 0.0 ); glVertex2f( 500, 400 ); //右下
glTexCoord2f( 1.0, 1.0 ); glVertex2f( 500, 200 ); //右上
glTexCoord2f( 0.0, 1.0 ); glVertex2f( 300, 200 ); //左上
*/
glEnd();
glutSwapBuffers();
glutPostRedisplay();
}
bool myInit()
{
//指定颜色和纹理坐标的差值质量,选择最高质量选项
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
//指定反走样点的采样质量,如果应用较大的滤波函数
//GL_NICEST在光栅化期间可以生成更多的像素段。
glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST );
//开启深度测试
glEnable( GL_DEPTH_TEST );
//开启二维纹理
glEnable( GL_TEXTURE_2D );
//读取纹理
bmp.readBMPFile("b2.bmp");
//设置纹理
bmp.setTexture();
//设置视角
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective(75, windowWidth/windowHeight, 1, 21);
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt(1, 5, 5, 0, 0, 0, 0, 0, 1);
/*第2种
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, windowWidth, 0, windowHeight );
*/
return true;
}
int main()
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(50, 50);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("DEMO");
myInit();
glutDisplayFunc(render);
glutMainLoop();
return 0;
}