OpenGL学习记录2
来源:互联网 发布:开设网络教育的学校 编辑:程序博客网 时间:2024/05/16 19:22
Exercise 2: 纹理
要求:
1. 在练习1的基础上,绘制一个带纹理的三角形;
2. 体现使用不同的纹理滤波方式(GL_NEAREST,GL_LINEAR)对结果的影响;
3. 使用超出1的纹理坐标,体现使用不同wrap参数(GL_REPEAT,GL_CLAMP)对结果的影响;
考察目的:
1. 纹理图像的载入;
2. OpenGL中基本纹理的使用;
3. 理解OpenGL中纹理滤波方式;
4. 理解OpenGL中的wrap参数;
5. 理解纹理映射中的走样问题(为什么会产生走样?怎样减少走样?);
by/scu xx
#include <windows.h>#include <gl/gl.h>#define GLUT_DISABLE_ATEXIT_HACK#include <glut.h>#include <iostream>#include <stdio.h>#include <stdlib.h> using namespace std; // 两种不同的纹理过滤GLuint texture[2]; // 判断使用哪种纹理两种纹理分别代表1// 由键盘l,n控制分别代表LINEAR滤波和Nearest滤波int selection = 0; // 读取bmp图片部分// 图片的类型包含宽高数据struct Image{ unsigned long sizeX; unsigned long sizeY; char *data;};typedef struct Image Image; //旋转参数static GLfloat xRot = 0.0f;static GLfloat yRot = 0.0f; //确定多边形绕法的方向BOOL bWinding = TRUE; int nStep = 0; static int g_mousePos_x = 0,g_mousePos_y = 0, g_tmpX, g_tmpY; bool g_rotate=false;//鼠标移动时的判断变量 //初始化窗口void SetupRC(void){ //设置窗口背景颜色为灰色 glClearColor(0.7f,0.7f, 0.7f, 1.0f );} void ChangeSize(int w,int h){ if(h == 0) h =1; glViewport(0, 0, w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* glOrtho(left,right, bottom, top, near, far), left表示视景体左面的坐标,right表示右面的坐标,bottom表示下面的,top表示上面的。 */ //建立修剪空间的范围 if (w <= h) glOrtho (-100.0f,100.0f, -100.0f*h/w, 100.0f*h/w, -100.0f, 100.0f); else glOrtho(-100.0f*w/h, 100.0f*w/h, -100.0f, 100.0f, -100.0f, 100.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity();} //在窗口中绘制图形void RenderScene(void){ glClear(GL_COLOR_BUFFER_BIT); GLfloat sizes[2]; //保存绘制点的尺寸范围 GLfloat step; //保存绘制点尺寸的步长 GLfloat curSize; //当前绘制的点的大小 glGetFloatv(GL_POINT_SIZE_RANGE,sizes);//获得点的尺寸范围 glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);//获得点尺寸的步长 //旋转图形 glPushMatrix(); glRotatef(xRot, 1.0f,0.0f, 0.0f); glRotatef(yRot, 0.0f,1.0f, 0.0f); //设置多边形绕法的方向是顺时针还是逆时针 if(bWinding) glFrontFace(GL_CW); else glFrontFace(GL_CCW); switch(nStep) { case 0: //绘制不同大小的点 curSize=sizes[0]; for (inti=0;i<25;i++) { glRotatef((GLfloat)g_mousePos_x, -1.0, 0.0, 0.0); glRotatef((GLfloat)g_mousePos_y, 0.0, -1.0, 0.0); glPointSize(curSize);//设置点的大小 glTexCoord2f(0.5f,0.5f); glBegin(GL_POINTS); glVertex3f(-80.0+i*8,0.0f, 0.0f); glEnd(); curSize+=step*2; } break; case 1: glRotatef((GLfloat)g_mousePos_x, -1.0, 0.0, 0.0); glRotatef((GLfloat)g_mousePos_y, 0.0, -1.0, 0.0); //绘制一条宽度为的直线 glLineWidth(5); //设置线宽 glBegin(GL_LINES); glTexCoord2f(0.0f,0.0f); glVertex3f(-70.0f,60.0f,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(70.0f,60.0f,0.0f); glEnd(); //绘制一条宽度为的直线 glLineWidth(3); //设置线宽 glBegin(GL_LINES); glTexCoord2f(0.0f,0.0f); glVertex3f(-70.0f,0.0f,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(70.0f,0.0f,0.0f); glEnd(); //绘制一条宽度为的直线 glLineWidth(1); //设置线宽 glBegin(GL_LINES); glTexCoord2f(0.0f,0.0f); glVertex3f(-70.0f,-60.0f,0.0f); glTexCoord2f(1.0f,1.0f); glVertex3f(70.0f,-60.0f,0.0f); glEnd(); break; case 2: //绘制三角形 glRotatef((GLfloat)g_mousePos_x, -1.0, 0.0, 0.0); glRotatef((GLfloat)g_mousePos_y, 0.0, -1.0, 0.0); glBindTexture(GL_TEXTURE_2D,texture[selection]); glBegin(GL_TRIANGLES); glTexCoord2f(0.0f,0.0f); glVertex3f(0, 60, 0); glTexCoord2f(1.0f,0.0f); glVertex3f(-60, -60, 0); glTexCoord2f(0.5f,1.0f); glVertex3f(60, -60, 0); glEnd(); break; case 3: //绘制矩形 glRotatef((GLfloat)g_mousePos_x, -1.0, 0.0, 0.0); glRotatef((GLfloat)g_mousePos_y, 0.0, -1.0, 0.0); glBindTexture(GL_TEXTURE_2D,texture[selection]); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex3f(60, 60, 0); glTexCoord2f(0.0f,1.0f); glVertex3f(60, -60, 0); glTexCoord2f(1.0f,1.0f); glVertex3f(-60, -60, 0); glTexCoord2f(1.0f,0.0f); glVertex3f(-60, 60, 0); glEnd(); break; } glPopMatrix(); glutSwapBuffers(); //刷新命令缓冲区 } void SpecialKeys(int key,int x,int y){ if(key == GLUT_KEY_UP) xRot-= 5.0f; if(key == GLUT_KEY_DOWN) xRot += 5.0f; if(key == GLUT_KEY_LEFT) yRot -= 5.0f; if(key == GLUT_KEY_RIGHT) yRot += 5.0f; if(xRot > 356.0f) xRot = 0.0f; if(xRot < -1.0f) xRot = 355.0f; if(yRot > 356.0f) yRot = 0.0f; if(yRot < -1.0f) yRot = 355.0f; //刷新窗口 glutPostRedisplay();} //键盘事件void KeyPressFunc(unsignedchar key,int x, int y){ if(key == 32) { nStep++; if(nStep > 3) nStep = 0; } switch(nStep) { case 0: glutSetWindowTitle("Points"); break; case 1: glutSetWindowTitle("Lines"); break; case 2: glutSetWindowTitle("Triangle"); break; case 3: glutSetWindowTitle("Rectangle"); break; } switch(key) { case 'l': case 'L': selection = 0; break; case 'n': case 'N': selection = 1; break; } glutPostRedisplay();} int ImageLoad(char*filename, Image *image){ FILE *file; unsigned long size;//图形的大小(字节数) unsigned long i; //标准计数器 unsigned shortint planes;//图形的平面数(必须为) unsigned shortint bpp;//每个像素的位数(必须为) char temp; //临时的颜色保存,bgr -rgb变换 // 确保文件存在。只读打开一个二进制文件,允许读数据 if ((file = fopen(filename, "rb"))== NULL) { printf("File Not Found: %s\n", filename); return 0; } // 用来设定文件的当前读取位置 // 意思是把文件的读写位置向后移动个字节,跳过文件的头部,准备读取宽度和高度 fseek(file, 18,SEEK_CUR); // 读取宽度 //fread(buffer,size,count,fp) //buffer:是一个指针,对fread来说,它是读入数据的存放地址 //size:要读写的字节数 //count:要进行读写多少个size字节的数据项 //fp:文件型指针 if ((i = fread(&image->sizeX, 4, 1, file)) !=1) { printf("Error reading width from %s. \n",filename); return 0; } printf("Width of %s: %lu\n", filename,image->sizeX); // 读取高度 if ((i = fread(&image->sizeY, 4, 1, file)) !=1) { printf("Error reading height from %s. \n",filename); return 0; } printf("Height of %s: %lu\n", filename,image->sizeY); // 计算图形的大小(每个像素bits或bytes) size =image->sizeX * image->sizeY * 3; // planes = getshort(file); if ((fread(&planes, 2, 1, file)) != 1) { printf("Error reading planes from %s. \n",filename); return 0; } if (planes != 1) { printf("Planes from %s is not 1: %u\n",filename, planes); return 0; } // bpp = getshort(file); if ((i = fread(&bpp, 2, 1, file)) != 1) { printf("Error reading bpp from %s. \n",filename); return 0; } if (bpp != 24) { printf("Bpp from %s is not 24: %u\n", filename,bpp); return 0; } // 跳过余下的头文件数据 fseek(file, 24,SEEK_CUR); // 读取数据 image->data = (char*) malloc (size); if (image->data == NULL) { printf("Error allocating memory for color-corrected imagedata"); return 0; } if ((i = fread(image->data, size, 1, file)) != 1) { printf("Error reading image data from %s. \n",filename); return 0; } // 交换颜色bgr -> rgb for (i = 0; i < size; i += 3) { temp =image->data[i]; image->data[i] = image->data[i+2]; image->data[i+2] = temp; } // 完成 return 1;} // 读取bitmaps并转化成纹理void LoadGLTextures(){ Image *image1; image1 = (Image*)malloc (sizeof(Image)); if (image1 == NULL) { printf("Error allocating space for image"); exit(0); } if (!ImageLoad("green.bmp",image1)) exit(1); // 线性滤波 // 指定纹理对象的数量和一个指针,这个指针指向一个无符号整型数组 glGenTextures(1,&texture[0]); glBindTexture(GL_TEXTURE_2D, texture[0]); // 绑定D纹理 // 当图片大于当前纹理时线性缩放 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 当图片小于当前纹理时线性缩放 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //void glTexImage2D(GLenum target, GLint level, GLintinternalformat, GLsizei width, GLsizei height, GLint border, GLenum format,GLenum type, void *data) //target变量用来指定一维、二维和三维的纹理贴图 //level参数指定了这些函数所加载的mip贴图层次。对于非mip贴图的纹理,总是可以把这个参数设置为 //internalformat参数会告诉OpenGL我们希望在每个纹理单元中储存多少颜色成分 //width、height指定了被加载纹理的宽度和高度,如果是三维则还有深度。这些值必须是的整数次方 //border参数允许为纹理贴图指定一个边界宽度。目前可以把这个值设置为 //最后个参数format、type和data与用于把图像数据放入颜色缓冲区的glDrawPixels函数的对应参数相同 glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, image1->data); // Nearest 滤波 glGenTextures(1,&texture[1]); glBindTexture(GL_TEXTURE_2D, texture[1]); // 绑定D纹理 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB,GL_UNSIGNED_BYTE, image1->data); } // 初始化opengl的一些参数void init(){ // 读取一张纹理 LoadGLTextures(); glEnable(GL_TEXTURE_2D); // 我们要使用纹理需要打开这个} void spinDisplay(void){ yRot -= 5.0f; if(yRot > 356.0f) yRot = 0.0f; if(yRot < -1.0f) yRot = 355.0f; glutPostRedisplay();} void mouse(int button,int state,int x,int z){ switch(button) { case GLUT_LEFT_BUTTON: if (state == GLUT_DOWN) { g_tmpX = x; g_tmpY = z; g_rotate = true; //鼠标移动时需要用到的判断变量 } else { g_rotate = false; } break; }} void motion(int x,int z){ if(g_rotate) { g_mousePos_y =(g_mousePos_y + (x - g_tmpX))%360; g_mousePos_x =(g_mousePos_x + (z - g_tmpY))%360; g_tmpX = x; g_tmpY = z; glutPostRedisplay(); }} int main(int argc,char* argv[]){ glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE| GLUT_RGB ); glutInitWindowSize(600,600);//这两个对窗口初始化的函数必须放在glutCreateWindow函数之前才会起效果 glutInitWindowPosition(100,100); glutCreateWindow("Points"); init(); glutReshapeFunc(ChangeSize); glutKeyboardFunc(KeyPressFunc);//对于当前的窗口设置keyboard的回调 glutSpecialFunc(SpecialKeys);//设置特殊键响应回调函数 glutMouseFunc(mouse); glutMotionFunc(motion); glutDisplayFunc(RenderScene); SetupRC(); glutMainLoop(); return 0;}
运行结果:
0 0
- OpenGL学习记录2
- OpenGL学习问题记录
- OpenGL学习记录1
- OpenGL学习记录3
- OpenGL学习记录4
- OpenGL学习记录5
- OpenGL学习记录6
- OpenGL学习记录7
- OpenGL入门学习记录
- OpenGL学习记录(1)
- 我的OpenGL学习记录1
- OpenGL学习记录——旋转矩形
- 画个三角形-----------openGL学习记录
- OPENGL记录
- Qt+openGL学习记录(2)`相机坐标移动的研究·
- OpenGL学习--2
- opengl学习随笔2
- OpenGL学习2
- 我在知乎回答关于 Linux C++ 服务端编程的学习方法
- CSS菜单实例:一款简单的CSS下拉菜单
- make clean与make distclean的区别
- Eclipse中使用自定义模板来弥补Myeclipse没有新建Filter的功能
- makefile 遗漏分隔符错误
- OpenGL学习记录2
- SQLServer数据库降级方法详解
- Clojure进阶:使用Clojure构建DSL
- 笔试随记(随时更新)
- cp: cannot create symbolic link Operation not permitted
- 13种常用按钮、文本框、表单等CSS样式
- 用户空间发送flow,packet操作告知内核处理过程
- 感悟:最近的一些想法
- android Select at least one project