(此节内容对应NEHE教程第24课)
应用.tga文件作为纹理数据来源进行纹理贴图
.tga图像文件数据格式:
0~~11 | 头信息 | |||||||
12~13 | 图像宽度 | byte[13]*256+byte[12] | ||||||
14~15 | 图像高度 | byte[15]*256+byte[14] | ||||||
16 | 图像每像素存储占用位(bit)数 | 24或32 | ||||||
18~end | 图片数据域 数据格式为GBRA,特殊需要需要转换 | 图片总大小=图像宽度*图像高度*(图像每像素存储占用位(bit)数/8) | ||||||
OpenGL可扩展性描述 | ||||||||
glGetString(GL_RENDERER) | 获取OpenGL相关信息 | |||||||
GL_VENDOR | 销售商 | |||||||
GL_RENDERER | OpenGL的实现组织 | |||||||
GL_VERSION | 当前版本 | |||||||
GL_EXTENSIONS | OpenGL扩展名 |
剪裁区域设置
glScissor函数用来设置剪裁区域,如果启用了GL_SCISSOR_TEST,绘制的内容只能在剪裁区域中显示。
glScissor(x,y,width,heigth);
glEnable(GL_SCISSOR_TEST);
应用剪裁区域 未应用剪裁区域
#include "header.h"
int scroll;
int maxtokens;
int swidth;
int sheight;
GLuint base;
typedef struct
{
GLubyte *imageData;
GLuint bpp;
GLuint width;
GLuint height;
GLuint texID;
} TextureImage;
TextureImage textures[1];
bool LoadTGA(TextureImage *texture, char *filename)
{
GLubyte TGAheader[12]={0,0,2,0,0,0,0,0,0,0,0,0};
GLubyte TGAcompare[12];
GLubyte header[6];
GLuint bytesPerPixel;
GLuint imageSize;
GLuint temp;
GLuint type=GL_RGBA;
FILE *file = fopen(filename, "rb");
if( file==NULL ||
fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||
memcmp(TGAheader,TGAcompare,sizeof(TGAheader))!=0 ||
fread(header,1,sizeof(header),file)!=sizeof(header))
{
if (file == NULL)
return false;
else
{
fclose(file);
return false;
}
}
texture->width = header[1] * 256 + header[0];
texture->height = header[3] * 256 + header[2];
if( texture->width <=0 ||
texture->height <=0 ||
(header[4]!=24 && header[4]!=32))
{
fclose(file);
return false;
}
texture->bpp = header[4];
bytesPerPixel = texture->bpp/8;
imageSize = texture->width*texture->height*bytesPerPixel;
texture->imageData=(GLubyte *)malloc(imageSize);
if( texture->imageData==NULL ||
fread(texture->imageData, 1, imageSize, file)!=imageSize)
{
if(texture->imageData!=NULL)
free(texture->imageData);
fclose(file);
return false;
}
for(GLuint i=0; i<int(imageSize); i+=bytesPerPixel)
{
temp=texture->imageData[i];
texture->imageData[i] = texture->imageData[i + 2];
texture->imageData[i + 2] = temp;
}
fclose (file);
// Build A Texture From The Data
glGenTextures(1, &texture[0].texID);
glBindTexture(GL_TEXTURE_2D, texture[0].texID);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (texture[0].bpp==24)
{
type=GL_RGB;
}
glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type, GL_UNSIGNED_BYTE, texture[0].imageData);
return true;
}
GLvoid BuildFont(GLvoid)
{
base=glGenLists(256);
glBindTexture(GL_TEXTURE_2D, textures[0].texID);
for (int loop1=0; loop1<256; loop1++)
{
float cx=float(loop1%16)/16.0f;
float cy=float(loop1/16)/16.0f;
glNewList(base+loop1,GL_COMPILE);
glBegin(GL_QUADS);
glTexCoord2f(cx,1.0f-cy-0.0625f);
glVertex2d(0,16);
glTexCoord2f(cx+0.0625f,1.0f-cy-0.0625f);
glVertex2i(16,16);
glTexCoord2f(cx+0.0625f,1.0f-cy-0.001f);
glVertex2i(16,0);
glTexCoord2f(cx,1.0f-cy-0.001f);
glVertex2i(0,0);
glEnd();
glTranslated(14,0,0);
glEndList();
}
}
GLvoid KillFont(GLvoid)
{
glDeleteLists(base,256);
}
GLvoid glPrint(GLint x, GLint y, int set, const char *fmt, ...)
{
char text[1024];
va_list ap;
if (fmt == NULL)
return;
va_start(ap, fmt);
vsprintf(text, fmt, ap);
va_end(ap);
if (set>1)
{
set=1;
}
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
glTranslated(x,y,0);
glListBase(base-32+(128*set));
glScalef(1.0f,2.0f,1.0f);
glCallLists(strlen(text),GL_UNSIGNED_BYTE, text);
glDisable(GL_TEXTURE_2D);
}
void ReSizeGLScene(GLsizei width, GLsizei height)
{
swidth=width;
sheight=height;
if (height==0)
{
height=1;
}
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f,640,480,0.0f,-1.0f,1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int InitGL(void)
{
if (!LoadTGA(&textures[0],"Data/Font.TGA"))
{
return false;
}
BuildFont();
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glBindTexture(GL_TEXTURE_2D, textures[0].texID);
return TRUE;
}
void DrawGLScene(void)
{
char *token;
int cnt=0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,0.5f,0.5f);
glPrint(50,16,1,"Renderer");
glPrint(80,48,1,"Vendor");
glPrint(66,80,1,"Version");
glColor3f(1.0f,0.7f,0.4f);
glPrint(200,16,1,(char *)glGetString(GL_RENDERER));
glPrint(200,48,1,(char *)glGetString(GL_VENDOR));
glPrint(200,80,1,(char *)glGetString(GL_VERSION));
glColor3f(0.5f,0.5f,1.0f);
glPrint(192,432,1,"NeHe Productions");
glLoadIdentity();
glColor3f(1.0f,1.0f,1.0f);
glBegin(GL_LINE_STRIP);
glVertex2d(639,417);
glVertex2d( 0,417);
glVertex2d( 0,480);
glVertex2d(639,480);
glVertex2d(639,128);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex2d( 0,128);
glVertex2d(639,128);
glVertex2d(639, 1);
glVertex2d( 0, 1);
glVertex2d( 0,417);
glEnd();
glScissor(1 ,int(0.135416f*sheight),swidth-2,int(0.597916f*sheight));
glEnable(GL_SCISSOR_TEST);
char* text=(char *)malloc(strlen((char *)glGetString(GL_EXTENSIONS))+1);
strcpy (text,(char *)glGetString(GL_EXTENSIONS));
token=strtok(text," ");
while(token!=NULL)
{
cnt++;
if (cnt>maxtokens)
{
maxtokens=cnt;
}
glColor3f(0.5f,1.0f,0.5f);
glPrint(0,96+(cnt*32)-scroll,0,"%i",cnt);
glColor3f(1.0f,1.0f,0.5f);
glPrint(50,96+(cnt*32)-scroll,0,token);
token=strtok(NULL," ");
}
glDisable(GL_SCISSOR_TEST);
free(text);
glFlush();
}
void keyboard(unsigned char key,int x,int y)
{
switch (key)
{
case 'W':
if (scroll>0)
{
scroll-=2;
}
glutPostRedisplay();
break;
case 'S':
if (scroll<32*(maxtokens-9))
{
scroll+=2;
}
glutPostRedisplay();
break;
}
}
int main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(800,600);
glutInitWindowPosition(100,100);
glutCreateWindow("区域剪裁和TGA图像文件的加载");
InitGL();
glutDisplayFunc(DrawGLScene);
glutKeyboardFunc(keyboard);
glutReshapeFunc(ReSizeGLScene);
glutMainLoop();
}