TGA格式图像是游戏中十分常见的一种图像格式,所以有必要了解其内部格式以及编程实现。
创新互联公司长期为千余家客户提供的网站建设服务,团队从业经验10年,关注不同地域、不同群体,并针对不同对象提供差异化的产品和服务;打造开放共赢平台,与合作伙伴共同营造健康的互联网生态环境。为仓山企业提供专业的做网站、成都网站制作,仓山网站改版等技术服务。拥有十多年丰富建站经验和众多成功案例,为您定制开发。TGA图像一般有非压缩和压缩两种格式,下面分别进行介绍。
一、非压缩TGA图像
注:前面的标记绿色的部分(共12字节)表示对于所有的非压缩TGA格式图像值都是相同的!所以通常用来在读取数据时鉴别是否为TGA图像。
下面的程序实现了绘制一个立方体,并进行纹理贴图。
需要注意的是:TGA图像中数据存放的顺序是BGR(A),而在OpenGL中顺序是RGB(A),所以在进行纹理生成的时候必须先进行格式的转化。
在OpenGL中只能加载24位或者32位的TGA图像生成纹理。
TGATexture.h定义了一些结构体以及函数声明:
[cpp] view plain?
#ifndef TGATEXTURE_H
#define TGATEXTURE_H
#include
#include
using namespace std;
//纹理结构体定义
typedef struct
{
GLubyte *p_w_picpathData;//图像数据
GLuint bpp;//像素深度
GLuint width;//图像宽度
GLuint height;//图像高度
GLuint texID;//对应的纹理ID
}TextureImage;
//加载TGA图像,生成纹理
bool LoadTGA(TextureImage *texture,char *fileName);
#endif
TGATexture.cpp则包含加载TGA图像生成纹理的函数具体实现:
[cpp] view plain?
#include "TGATexture.h"
//加载TGA图像(无压缩格式),生成纹理
bool LoadTGA(TextureImage *texture, char *filename) // Loads A TGA File Into Memory
{
GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0}; // Uncompressed TGA Header
GLubyte TGAcompare[12]; // Used To Compare TGA Header
GLubyte header[6]; // First 6 Useful Bytes From The Header
GLuint bytesPerPixel; // Holds Number Of Bytes Per Pixel Used In The TGA File
GLuint p_w_picpathSize; // Used To Store The Image Size When Setting Aside Ram
GLuint temp; // Temporary Variable
GLuint type=GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP)
FILE *file = fopen(filename, "rb"); // Open The TGA File
if( file==NULL || // Does File Even Exist?
fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) || // Are There 12 Bytes To Read?
memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 || // Does The Header Match What We Want?
fread(header,1,sizeof(header),file)!=sizeof(header)) // If So Read Next 6 Header Bytes
{
if (file == NULL) // Did The File Even Exist? *Added Jim Strong*
return false; // Return False
else
{
fclose(file); // If Anything Failed, Close The File
return false; // Return False
}
}
texture->width = header[1] * 256 + header[0]; // Determine The TGA Width (highbyte*256+lowbyte)
texture->height = header[3] * 256 + header[2]; // Determine The TGA Height (highbyte*256+lowbyte)
//OpenGL中纹理只能使用24位或者32位的TGA图像
if( texture->width <=0 || // Is The Width Less Than Or Equal To Zero
texture->height <=0 || // Is The Height Less Than Or Equal To Zero
(header[4]!=24 && header[4]!=32)) // Is The TGA 24 or 32 Bit?
{
fclose(file); // If Anything Failed, Close The File
return false; // Return False
}
texture->bpp = header[4]; // Grab The TGA's Bits Per Pixel (24 or 32)
bytesPerPixel = texture->bpp/8; // Divide By 8 To Get The Bytes Per Pixel
p_w_picpathSize = texture->width*texture->height*bytesPerPixel; // Calculate The Memory Required For The TGA Data
texture->p_w_picpathData=(GLubyte *)malloc(p_w_picpathSize); // Reserve Memory To Hold The TGA Data
if( texture->p_w_picpathData==NULL || // Does The Storage Memory Exist?
fread(texture->p_w_picpathData, 1, p_w_picpathSize, file)!=p_w_picpathSize) // Does The Image Size Match The Memory Reserved?
{
if(texture->p_w_picpathData!=NULL) // Was Image Data Loaded
free(texture->p_w_picpathData); // If So, Release The Image Data
fclose(file); // Close The File
return false; // Return False
}
//RGB数据格式转换,便于在OpenGL中使用
for(GLuint i=0; i
{ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
temp=texture->p_w_picpathData[i]; // Temporarily Store The Value At Image Data 'i'
texture->p_w_picpathData[i] = texture->p_w_picpathData[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte
texture->p_w_picpathData[i + 2] = temp; // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
}
fclose (file); // Close The File
// Build A Texture From The Data
glGenTextures(1, &texture[0].texID); // Generate OpenGL texture IDs
glBindTexture(GL_TEXTURE_2D, texture[0].texID); // Bind Our Texture
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Filtered
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtered
if (texture[0].bpp==24) // Was The TGA 24 Bits
{
type=GL_RGB; // If So Set The 'type' To GL_RGB
}
glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].p_w_picpathData);
return true; // Texture Building Went Ok, Return True
}
main.cpp主程序:
[cpp] view plain?
#include "TGATexture.h"
TextureImage texture[1];
GLfloat xRot,yRot,zRot;//control cube's rotation
int init()
{
if(!LoadTGA(&texture[0],"GSK1.tga"))
return GL_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);
return GL_TRUE;
}
void display()
{
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);
// Front Face
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
// Back Face
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
// Top Face
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
// Bottom Face
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
// Right face
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glEnd();
glBindTexture(GL_TEXTURE_2D,texture[0].texID);
glBegin(GL_QUADS);
// Left Face
// Bottom Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
// Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Top Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
glutSwapBuffers();
}
void reshape(int w,int h)
{
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();
}
void keyboard(unsigned char key,int x,int y)
{
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;
}
}
int main(int argc,char** argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400,400);
glutInitWindowPosition(100,100);
glutCreateWindow("Texture Map");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。