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

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

2011-08-28 21:19 423 查看


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

今天是学习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



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