访问次数
我的另一个总结性博客: todototry 大米粒

OpenGL 纹理映射 ---画三维de篱笆

以上是我今天练习的一段纹理贴图程序的效果图

今天是学习OpenGL第九天,一天一个小例子,写了九段程序了,一直以来都想着要为自己画得三维图 变得 真实一点。

这一个小程序算是向这一个小目标更加接近了一点。

但是也发现蛮多问题。 ------------希望能够得到 有经验的朋友指点

1.OpenGL的各种状态,在设置Projection状态的时候做了什么, 能做什么,

modelView 状态又能做什么?viewport是干嘛用的?这些状态搞不清楚 做什么事情的时候需要转变状态。设定错了出不来想要的 openGL也不会提示。真是无奈。

2.Projection状态时的坐标规则。view 状态。

3.gluPerspective 视线角稍微容易设定一点,可是 gluLookAt 这一大堆参数的用处倒是知道,只是自己设定的时候还是不知道设定 它 为自己想要的视点

4.设定glTexCoord2f 和 glVertex3f 是怎么对应,repeat 的

代码如下:

#include "windows.h"
#include
"gl/gl.h"
#include
"gl/glu.h"
#include
"gl/glut.h"
#include
<stdio.h>

#define BmpHeaderLength 54 //文件长度
#define WidthPosition 0x0012 //width值在文件中的位置
#define HeightPosition 0x0016 //height在文件中的位置

typedef
struct{

char *filename; //文件名
FILE *fp; //文件指针
GLint width; //
GLint height; //
GLubyte * pPixelData; //文件中 实际的像素信息

}FileDataInfo;
//文件数据信息

GLuint texGround;
GLuint texWall;

FileDataInfo LoadBMP(
char *filename)
{

FileDataInfo fileinfo;
fileinfo.filename
= filename;
fileinfo.fp
= fopen(fileinfo.filename,"rb");

fseek(fileinfo.fp,WidthPosition,SEEK_SET);
fread(
&fileinfo.width,sizeof(fileinfo.width),1,fileinfo.fp);

fseek(fileinfo.fp,HeightPosition,SEEK_SET);
fread(
&fileinfo.height,sizeof(fileinfo.height),1,fileinfo.fp);

fseek(fileinfo.fp,BmpHeaderLength,SEEK_SET);


int widthInBmpFile = fileinfo.width*3;

//因为微软的bmp格式文件宽度 像素值 是 4 整数倍,不是的话,会在后面补上,
//也就是说 (像素宽*3)*像素高 <= 文件大小-54; ---54是bmp文件头部大小。
//所以在读取文件的时候需要调整内存大小,而不是 直接的(width*3)*height ;
while(widthInBmpFile%4 != 0)
{
widthInBmpFile
++;
}

int pixelDataLen = widthInBmpFile *fileinfo.height;
fileinfo.pPixelData
= (GLubyte*)malloc(pixelDataLen);

if(fileinfo.pPixelData == 0)
{
printf(
"malloc() failed");

free(fileinfo.pPixelData);

exit(
0);
}

fread(fileinfo.pPixelData,pixelDataLen,
1,fileinfo.fp);

fclose(fileinfo.fp);

return fileinfo;
}


//释放资源
void destroy(FileDataInfo *p)
{
free(p
->pPixelData);
fclose(p
->fp);
}

int getTexture(FileDataInfo fileinfo)
{
GLuint last_texture_ID,texture_ID
=0;
GLubyte
* pTextureData;
GLubyte
* newData ;
GLint max;

//OpenGL 低版本中,纹理大小不能超过 一定值。
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&max);

//为保证openGL向低版本的兼容性,超过了的话,需要将其缩小。
if(fileinfo.width > max||fileinfo.height >max)
{
//最大宽 和 高
int maxWidth =256;
int maxHeight = 256;


int lines = (int)maxWidth*3;

if(lines % 4 != 0)
{
lines
++;
}

int total = lines * maxHeight;

newData
= (GLubyte*)malloc(total);

if(newData == 0)
{
printf(
"newData=malloc() failed");
return -1;
}

//缩小
gluScaleImage(GL_RGB,fileinfo.width,fileinfo.height,GL_UNSIGNED_BYTE,fileinfo.pPixelData,maxWidth,maxHeight,GL_UNSIGNED_BYTE,newData);

pTextureData
= newData;

}
else
{
pTextureData
= fileinfo.pPixelData;

}

//generate a texture ID
glGenTextures(1,&texture_ID);

if(texture_ID == 0)
{
free(pTextureData);
printf(
"get textureID failed !");
return -1;
}

glGetIntegerv(GL_TEXTURE_BINDING_2D,(GLint
*)&last_texture_ID);

glBindTexture(GL_TEXTURE_2D,texture_ID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);

glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);

glTexImage2D(GL_TEXTURE_2D,
0,GL_RGB,fileinfo.width,fileinfo.height,0,GL_BGR_EXT,GL_UNSIGNED_BYTE,pTextureData);
glBindTexture(GL_TEXTURE_2D,last_texture_ID);

return texture_ID;
}




void display()
{
glClear(GL_COLOR_BUFFER_BIT
|GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(
65,1,1,21);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(
1,5,5,0,0,0,0,0,1);


//开始绑定地表图像 作为纹理
glBindTexture(GL_TEXTURE_2D,texGround);

glBegin(GL_QUADS);
glTexCoord2f(
0.0f,0.0f); glVertex3f(-8.0f,-8.0f,0.0f);
glTexCoord2f(
0.0,5.0f); glVertex3f(-8.0f,8.0f,0.0f);
glTexCoord2f(
5.0f,5.0f); glVertex3f(8.0f,8.0f,0.0f);
glTexCoord2f(
5.0f,0.0f); glVertex3f(8.0f,-8.0f,0.0f);
glEnd();



// 使用“墙”纹理绘制栅栏
glBindTexture(GL_TEXTURE_2D, texWall);

glBegin(GL_QUADS);
glTexCoord2f(
0.0f, 0.0f); glVertex3f(-6.0f, -3.0f, 0.0f);
glTexCoord2f(
0.0f, 1.0f); glVertex3f(-6.0f, -3.0f, 1.5f);
glTexCoord2f(
5.0f, 1.0f); glVertex3f(6.0f, -3.0f, 1.5f);
glTexCoord2f(
5.0f, 0.0f); glVertex3f(6.0f, -3.0f, 0.0f);
glEnd();

// 旋转后再绘制一个
glRotatef(-90, 0, 0, 1);

glBegin(GL_QUADS);
glTexCoord2f(
0.0f, 0.0f); glVertex3f(-6.0f, -3.0f, 0.0f);
glTexCoord2f(
0.0f, 1.0f); glVertex3f(-6.0f, -3.0f, 1.5f);
glTexCoord2f(
5.0f, 1.0f); glVertex3f(6.0f, -3.0f, 1.5f);
glTexCoord2f(
5.0f, 0.0f); glVertex3f(6.0f, -3.0f, 0.0f);
glEnd();


// 交换缓冲区,并保存像素数据到文件
glutSwapBuffers();

}

int main(int argc, char ** argv)
{
glutInit(
&argc,argv);
glutInitDisplayMode(GLUT_RGBA
|GLUT_DOUBLE);

glutInitWindowPosition(
100,100);
glutInitWindowSize(
500,500);
glutCreateWindow(
"Texture Image");

glutDisplayFunc(
&display);

glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);


FileDataInfo groundFileInfo
= LoadBMP("ground.bmp");
texGround
= getTexture(groundFileInfo);

FileDataInfo wallFileInfo
= LoadBMP("wall.bmp");
texWall
= getTexture(wallFileInfo);

glutMainLoop();

destroy(
&groundFileInfo);
destroy(
&wallFileInfo);

return 0;
}

ground.bmp

wall.bmp

//结果

posted @ 2011-08-28 21:19  fandyst  阅读(844)  评论(0编辑  收藏  举报