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

opengl中TGA图像加载技术

2016-07-26 18:00 375 查看
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 *imageData;//图像数据

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 imageSize; // 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

imageSize = texture->width*texture->height*bytesPerPixel; // Calculate The Memory Required For The TGA Data

texture->imageData=(GLubyte *)malloc(imageSize); // Reserve Memory To Hold The TGA Data

if( texture->imageData==NULL || // Does The Storage Memory Exist?

fread(texture->imageData, 1, imageSize, file)!=imageSize) // Does The Image Size Match The Memory Reserved?

{

if(texture->imageData!=NULL) // Was Image Data Loaded

free(texture->imageData); // If So, Release The Image Data

fclose(file); // Close The File

return false; // Return False

}

//RGB数据格式转换,便于在OpenGL中使用

for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel) // Loop Through The Image Data

{ // Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)

temp=texture->imageData[i]; // Temporarily Store The Value At Image Data 'i'

texture->imageData[i] = texture->imageData[i + 2]; // Set The 1st Byte To The Value Of The 3rd Byte

texture->imageData[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].imageData);

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;

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