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
原创粉丝点击