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

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

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

      如:

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

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

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

vector<unsigned int> V_ID;          //用来保存生成的纹理id
int 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 0x4D42
float h,m,s;
using std::vector;
using std::cout;
using std::endl;
int LoadBitmap(const char *file)
{
	unsigned int ID;      //纹理的id
	int 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;          //用来保存生成的纹理id
int 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);
	else
		glColor4f(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;
}




你可能感兴趣的:(OpenGL织梦之旅【第三章】第2节.循环显示图片)