OpenGL织梦之旅【第三章】第2节.循环显示图片

来源:互联网 发布:苗立杰wnba数据 编辑:程序博客网 时间:2024/06/05 02:41

        这节我们将读取几个图片,生成一个纹理集,然后让程序循环显示图片。

      为了方便,我直接把图片的数量和每个图片的名字保存在一个txt文档里面,方便程序地读取。

      如:


        在init函数中,打开data.txt,读取图片的数量和图片的名字,然后调用LoadBitmap函数,把所生成的纹理保存在一个容器vector中,然后在Update函数中,控制显示的图片id,从而达到循环显示。

        具体的实现很简单,所以就不多说了~

vector<unsigned int> V_ID;          //用来保存生成的纹理idint now,cnt;                        //now是当前所使用的纹理在vector中的下标//cnt是用来计时的变量void Update(){cnt++;if (cnt >= 100)               //当cnt加到的时候,换下一张图片{now++;now%=V_ID.size();         //保证now值的正确性cnt=0;                    //将cnt值置,开始下一个图片的显示}    glutPostRedisplay();}void init(){int n,i;char str[100],file[100];V_ID.clear();                         //清空容器FILE *fp;fp=fopen("data/data.txt","r");fscanf(fp,"%d",&n);while (n--){fscanf(fp,"%s",str);sprintf(file,"data/%s",str);      i=LoadBitmap(file);if (i == -1)                       //读取图片失败continue;else                                 V_ID.push_back(i);             //把图片的id放到V_ID的末尾保存起来}fclose(fp);now=0;}


        图片实现了循环以后呢,我还希望图片在交替的时候,有一个淡入淡出的效果。怎么做呢?

        还记得glColor3f函数吧,这个函数有一个可以带4个参数的形式:glColor4f

        这里的第四个参数,也就是alpha值。我们通过OpenGL提供的颜色混合功能,使用alpha值来实现这个效果。

        在生活中,如果把两张照片(不透明)叠在一起,很明显,我们只能看见在最顶上的那张照片。如果一张照片被处理了,变成了透明的,那么我们就可以看见两张照片了。在OpenGL中,如果我们在一个区域画了一个绿色的矩形,随后在同样的区域画了一个黄色的矩形,那么我们就只能看见黄色的矩形,因为新画得黄矩形把原来那个覆盖了。如果我们想看见两个不同颜色矩形叠加在一起的效果,通过alpha混合就可以创建半透明的图像片段。

        要使用alpha值,首先要开启混合功能。调用glEnable(GL_BLEND);

        然后就是glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);这个函数是指定了两个图像片断混合的方式,在绘制图片之前,我们先调用glColor4f(1.0,1.0,1.0,alpha);

        其中alpha值是[0,1]之间的,如果定为1,就是不透明,定为0就是,完全透明。淡入淡出的实现其实就是让这个值在[0,1]之间浮动即可。

所以,根据cnt值的变化,进行如下的操作:

if (cnt <= 50)      glColor4f(1.0,1.0,1.0,(float)cnt/50.0);   else   glColor4f(1.0,1.0,1.0,1.0-((float)cnt-50.0)/50.0);


至于为什么前面的RGB为什么是,1,1,1,你可以尝试把某个改成0,看看效果^_^。

附本节代码:

#include <GL/glut.h>#include <stdio.h>#include <math.h>#include <time.h>#include <stdlib.h>#include <windows.h>#include <vector>#include <iostream>#define PI 3.1415926#define BITMAP_ID 0x4D42float h,m,s;using std::vector;using std::cout;using std::endl;int LoadBitmap(const char *file){unsigned int ID;      //纹理的idint width,height,i;   byte *image,t;          //接受图像数据FILE *fp;             //文件指针BITMAPFILEHEADER FileHeader;     //接受位图文件头BITMAPINFOHEADER InfoHeader;     //接受位图信息头fp=fopen(file,"rb");if (fp == NULL){perror("LoadBitmap");        //打开文件失败return -1;}fread(&FileHeader, sizeof(BITMAPFILEHEADER), 1, fp);if(FileHeader.bfType != BITMAP_ID)   //确保文件是一个位图文件,效验文件类型{ printf("Error: This file is not a bmp file!");fclose(fp);return -1;}fread(&InfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);width=InfoHeader.biWidth; height=InfoHeader.biHeight;if (InfoHeader.biSizeImage == 0)           //确保图像数据的大小    {   InfoHeader.biSizeImage = width*height*3;}fseek(fp, FileHeader.bfOffBits, SEEK_SET);  //将文件指针移动到实际图像数据处image=(byte *)malloc(sizeof(byte)*InfoHeader.biSizeImage); //申请空间if (image == NULL){free(image);printf("Error: No enough space!");return -1;}fread(image, 1, InfoHeader.biSizeImage, fp);for(i=0; i<InfoHeader.biSizeImage; i+=3){   t=image[i];   image[i]=image[i+2];   image[i+2]=t;}fclose(fp);  glGenTextures(1, &ID);    glBindTexture(GL_TEXTURE_2D, 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_CLAMP);    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width,                  height, GL_RGB, GL_UNSIGNED_BYTE,                  image);return ID;  }vector<unsigned int> V_ID;          //用来保存生成的纹理idint now,cnt;                        //now是当前所使用的纹理在vector中的下标//cnt是用来计时的变量void Draw(){    glClearColor(0.0,0.0,0.0,0.0);    glClear(GL_COLOR_BUFFER_BIT);   glEnable(GL_TEXTURE_2D);    glBindTexture(GL_TEXTURE_2D, V_ID[now]);glEnable(GL_BLEND);    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);if (cnt <= 50)glColor4f(1.0,1.0,1.0,(float)cnt/50.0);elseglColor4f(1.0,1.0,1.0,1.0-((float)cnt-50.0)/50.0);glBegin(GL_QUADS);glTexCoord2f(0.0f, 0.0f);glVertex2f(-1,-1);glTexCoord2f(1.0f, 0.0f);glVertex2f(1,-1);glTexCoord2f(1.0f, 1.0f);glVertex2f(1,1);glTexCoord2f(0.0f, 1.0f);glVertex2f(-1,1);glEnd();glDisable(GL_TEXTURE_2D);  glutSwapBuffers();}void Update(){cnt++;if (cnt >= 100)               //当cnt加到100的时候,换下一张图片{now++;now%=V_ID.size();         //保证now值的正确性cnt=0;                    //将cnt值置0,开始下一个图片的显示}    glutPostRedisplay();}void Reshape(int w,int h){    w=w>h?h:w;    glViewport(0,0,(GLsizei)w,(GLsizei)w);}void init(){int n,i;char str[100],file[100];V_ID.clear();                         //清空容器FILE *fp;fp=fopen("data/data.txt","r");fscanf(fp,"%d",&n);while (n--){fscanf(fp,"%s",str);sprintf(file,"data/%s",str);      i=LoadBitmap(file);if (i == -1)                       //读取图片失败continue;else                                 V_ID.push_back(i);             //把图片的id放到V_ID的末尾保存起来}fclose(fp);now=0;}int main(int argc, char *argv[]){    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);    glutInitWindowPosition(100, 100);    glutInitWindowSize(400, 400);    glutCreateWindow("HelloOpenGL");    glutReshapeFunc(&Reshape);    glutIdleFunc(&Update);    glutDisplayFunc(&Draw);init();    glutMainLoop();    return 0;}