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
//结果
相关文章推荐
- 【OpenGL】(NeHe教程学习)纹理映射及代码实现
- OpenGL纹理映射总结
- OpenGL纹理映射--基础篇
- OpenGl 第七章:纹理映射 (texture mapping)
- openGL纹理映射参数解析
- OpenGL学习(七)纹理映射
- ArchieOpenGL基础教程第八课:创建3D图形和纹理映射(MFC/SDI)
- opengl编程学习笔记(四)(纹理映射)(结合nvdia OpenglSDk 的nvimage类)
- Qt_OpenGL:纹理映射小测
- OpenGL 纹理映射
- OpenGL 纹理坐标 和 顶点坐标映射关系 详解
- OpenGL蓝宝书第五章5.4Tunnuel 纹理映射和过滤:较好的可读性代码
- OpenGL 纹理映射
- OpenGL天空贴图以及反射纹理映射即镜面反射
- OpenGL 4.0 GLSL 实现 投影纹理映射(Projective Texture Mapping)
- opengl中的纹理映射
- Opengl纹理映射(转)
- opengl纹理映射总结
- OpenGL蓝宝书第六章代码疑虑:为什么使用了GL_TEXTURE_1D??纹理和顶点间的映射是如何实现?
- OpenGL学习 将不同纹理映射到不同面上