您好,登錄后才能下訂單哦!
TGA格式圖像是游戲中十分常見的一種圖像格式,所以有必要了解其內部格式以及編程實現。
TGA圖像一般有非壓縮和壓縮兩種格式,下面分別進行介紹。
一、非壓縮TGA圖像
注:前面的標記綠色的部分(共12字節)表示對于所有的非壓縮TGA格式圖像值都是相同的!所以通常用來在讀取數據時鑒別是否為TGA圖像。
下面的程序實現了繪制一個立方體,并進行紋理貼圖。
需要注意的是:TGA圖像中數據存放的順序是BGR(A),而在OpenGL中順序是RGB(A),所以在進行紋理生成的時候必須先進行格式的轉化。
在OpenGL中只能加載24位或者32位的TGA圖像生成紋理。
TGATexture.h定義了一些結構體以及函數聲明:
[cpp] view plain copy print?
#ifndef TGATEXTURE_H
#define TGATEXTURE_H
#include <GL/glut.h>
#include <iostream>
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 copy print?
#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<int(p_w_picpathSize); i+=bytesPerPixel) // Loop Through The Image Data
{ // 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 copy print?
#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;
}
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。