opengl中TGA图像加载技术
TGA格式图像是游戏中十分常见的一种图像格式,所以有必要了解其内部格式以及编程实现。
TGA图像一般有非压缩和压缩两种格式,下面分别进行介绍。
一、非压缩TGA图像
注:前面的标记绿色的部分(共12字节)表示对于所有的非压缩TGA格式图像值都是相同的!所以通常用来在读取数据时鉴别是否为TGA图像。
下面的程序实现了绘制一个立方体,并进行纹理贴图。
需要注意的是:TGA图像中数据存放的顺序是BGR(A),而在OpenGL中顺序是RGB(A),所以在进行纹理生成的时候必须先进行格式的转化。
在OpenGL中只能加载24位或者32位的TGA图像生成纹理。
TGATexture.h定义了一些结构体以及函数声明:
[cpp]view plaincopyprint?
#ifndefTGATEXTURE_H
#defineTGATEXTURE_H
#include<GL/glut.h>
#include<iostream>
usingnamespacestd;
//纹理结构体定义
typedefstruct
{
GLubyte*p_w_picpathData;//图像数据
GLuintbpp;//像素深度
GLuintwidth;//图像宽度
GLuintheight;//图像高度
GLuinttexID;//对应的纹理ID
}TextureImage;
//加载TGA图像,生成纹理
boolLoadTGA(TextureImage*texture,char*fileName);
#endif
TGATexture.cpp则包含加载TGA图像生成纹理的函数具体实现:
[cpp]view plaincopyprint?
#include"TGATexture.h"
//加载TGA图像(无压缩格式),生成纹理
boolLoadTGA(TextureImage*texture,char*filename)//LoadsATGAFileIntoMemory
{
GLubyteTGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};//UncompressedTGAHeader
GLubyteTGAcompare[12];//UsedToCompareTGAHeader
GLubyteheader[6];//First6UsefulBytesFromTheHeader
GLuintbytesPerPixel;//HoldsNumberOfBytesPerPixelUsedInTheTGAFile
GLuintp_w_picpathSize;//UsedToStoreTheImageSizeWhenSettingAsideRam
GLuinttemp;//TemporaryVariable
GLuinttype=GL_RGBA;//SetTheDefaultGLModeToRBGA(32BPP)
FILE*file=fopen(filename,"rb");//OpenTheTGAFile
if(file==NULL||//DoesFileEvenExist?
fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare)||//AreThere12BytesToRead?
memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0||//DoesTheHeaderMatchWhatWeWant?
fread(header,1,sizeof(header),file)!=sizeof(header))//IfSoReadNext6HeaderBytes
{
if(file==NULL)//DidTheFileEvenExist?*AddedJimStrong*
returnfalse;//ReturnFalse
else
{
fclose(file);//IfAnythingFailed,CloseTheFile
returnfalse;//ReturnFalse
}
}
texture->width=header[1]*256+header[0];//DetermineTheTGAWidth(highbyte*256+lowbyte)
texture->height=header[3]*256+header[2];//DetermineTheTGAHeight(highbyte*256+lowbyte)
//OpenGL中纹理只能使用24位或者32位的TGA图像
if(texture->width<=0||//IsTheWidthLessThanOrEqualToZero
texture->height<=0||//IsTheHeightLessThanOrEqualToZero
(header[4]!=24&&header[4]!=32))//IsTheTGA24or32Bit?
{
fclose(file);//IfAnythingFailed,CloseTheFile
returnfalse;//ReturnFalse
}
texture->bpp=header[4];//GrabTheTGA'sBitsPerPixel(24or32)
bytesPerPixel=texture->bpp/8;//DivideBy8ToGetTheBytesPerPixel
p_w_picpathSize=texture->width*texture->height*bytesPerPixel;//CalculateTheMemoryRequiredForTheTGAData
texture->p_w_picpathData=(GLubyte*)malloc(p_w_picpathSize);//ReserveMemoryToHoldTheTGAData
if(texture->p_w_picpathData==NULL||//DoesTheStorageMemoryExist?
fread(texture->p_w_picpathData,1,p_w_picpathSize,file)!=p_w_picpathSize)//DoesTheImageSizeMatchTheMemoryReserved?
{
if(texture->p_w_picpathData!=NULL)//WasImageDataLoaded
free(texture->p_w_picpathData);//IfSo,ReleaseTheImageData
fclose(file);//CloseTheFile
returnfalse;//ReturnFalse
}
//RGB数据格式转换,便于在OpenGL中使用
for(GLuinti=0;i<int(p_w_picpathSize);i+=bytesPerPixel)//LoopThroughTheImageData
{//SwapsThe1stAnd3rdBytes('R'edand'B'lue)
temp=texture->p_w_picpathData[i];//TemporarilyStoreTheValueAtImageData'i'
texture->p_w_picpathData[i]=texture->p_w_picpathData[i+2];//SetThe1stByteToTheValueOfThe3rdByte
texture->p_w_picpathData[i+2]=temp;//SetThe3rdByteToTheValueIn'temp'(1stByteValue)
}
fclose(file);//CloseTheFile
//BuildATextureFromTheData
glGenTextures(1,&texture[0].texID);//GenerateOpenGLtextureIDs
glBindTexture(GL_TEXTURE_2D,texture[0].texID);//BindOurTexture
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//LinearFiltered
glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);//LinearFiltered
if(texture[0].bpp==24)//WasTheTGA24Bits
{
type=GL_RGB;//IfSoSetThe'type'ToGL_RGB
}
glTexImage2D(GL_TEXTURE_2D,0,type,texture[0].width,texture[0].height,0,type,GL_UNSIGNED_BYTE,texture[0].p_w_picpathData);
returntrue;//TextureBuildingWentOk,ReturnTrue
}
main.cpp主程序:
[cpp]view plaincopyprint?
#include"TGATexture.h"
TextureImagetexture[1];
GLfloatxRot,yRot,zRot;//controlcube'srotation
intinit()
{
if(!LoadTGA(&texture[0],"GSK1.tga"))
returnGL_FALSE;
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f,0.0f,0.0f,0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
returnGL_TRUE;
}
voiddisplay()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-5.0f);
glRotatef(xRot,1.0f,0.0f,0.0f);
glRotatef(yRot,0.0f,1.0f,0.0f);
glRotatef(zRot,0.0f,0.0f,1.0f);
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
//FrontFace
//BottomLeftOfTheTextureandQuad
glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);
//BottomRightOfTheTextureandQuad
glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);
//TopRightOfTheTextureandQuad
glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);
//TopLeftOfTheTextureandQuad
glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
//BackFace
//BottomRightOfTheTextureandQuad
glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);
//TopRightOfTheTextureandQuad
glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);
//TopLeftOfTheTextureandQuad
glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);
//BottomLeftOfTheTextureandQuad
glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
//TopFace
//TopLeftOfTheTextureandQuad
glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);
//BottomLeftOfTheTextureandQuad
glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,1.0f,1.0f);
//BottomRightOfTheTextureandQuad
glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,1.0f,1.0f);
//TopRightOfTheTextureandQuad
glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
//BottomFace
//TopRightOfTheTextureandQuad
glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,-1.0f,-1.0f);
//TopLeftOfTheTextureandQuad
glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,-1.0f,-1.0f);
//BottomLeftOfTheTextureandQuad
glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);
//BottomRightOfTheTextureandQuad
glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
//Rightface
//BottomRightOfTheTextureandQuad
glTexCoord2f(1.0f,0.0f);glVertex3f(1.0f,-1.0f,-1.0f);
//TopRightOfTheTextureandQuad
glTexCoord2f(1.0f,1.0f);glVertex3f(1.0f,1.0f,-1.0f);
//TopLeftOfTheTextureandQuad
glTexCoord2f(0.0f,1.0f);glVertex3f(1.0f,1.0f,1.0f);
//BottomLeftOfTheTextureandQuad
glTexCoord2f(0.0f,0.0f);glVertex3f(1.0f,-1.0f,1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
//LeftFace
//BottomLeftOfTheTextureandQuad
glTexCoord2f(0.0f,0.0f);glVertex3f(-1.0f,-1.0f,-1.0f);
//BottomRightOfTheTextureandQuad
glTexCoord2f(1.0f,0.0f);glVertex3f(-1.0f,-1.0f,1.0f);
//TopRightOfTheTextureandQuad
glTexCoord2f(1.0f,1.0f);glVertex3f(-1.0f,1.0f,1.0f);
//TopLeftOfTheTextureandQuad
glTexCoord2f(0.0f,1.0f);glVertex3f(-1.0f,1.0f,-1.0f);
glEnd();
glutSwapBuffers();
}
voidreshape(intw,inth)
{
if(0==h)
h=1;
glViewport(0,0,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f,(GLfloat)w/(GLfloat)h,1,100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
voidkeyboard(unsignedcharkey,intx,inty)
{
switch(key){
case'x':
xRot+=1.0f;
glutPostRedisplay();
break;
case'y':
yRot+=1.0f;
glutPostRedisplay();
break;
case'z':
zRot+=1.0f;
glutPostRedisplay();
break;
default:
break;
}
}
intmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize(400,400);
glutInitWindowPosition(100,100);
glutCreateWindow("TextureMap");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return0;
}
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。