有时我们希望上层的图片的某些区域能投出下层的某些区域。当然我们可以通过关
键色进行处理,但是蒙版技术一样可以达到这样的效果,通过以下图片达到蒙版的效果
本节包含2个技术点
1.如何让纹理移动,放大(不是图像位置移动,是纹理移动)(前面以及介绍过了)
2.蒙版的设计
蒙版设计简单的说是通过控制Alpha来让白色的部分透,黑色的部分不透
蒙版的设计
1.第一张图与第二张图进行混合(1下2上),期望达到的效果是2图黑色部分不透,白色部分透到1图
分析:R新=Rs+Rd; G新=Gs+Gd; B新=Bs+Bd;其实S为图2,D为图1
期望效果:图2黑色区域:R新=Rd;G新=Gd; B新=Bd;
图2白色区域:R新=Rs;G新=Gs; B新=Bs;
因此glBlendFunc(GL_DST_COLOR,GL_ZERO);方式进行混合的时候满足要求
2.第三张图与前两张混合,期望达到的效果是图3黑色区域透,非黑区域不透(S为图3,D为上一步混合图)
期望效果:图3黑色区域:R新=Rd;G新=Gd; B新=Bd;
图3非黑色区域:R新=Rs;G新=Gs; B新=Bs;
因此 glBlendFunc(GL_ONE, GL_ONE) ;方式进行混合的时候满足要求
总结,蒙版技术看似2个图的混合,是指为3个图的混合而成,
我们期望达到的效果是图3黑色区域透出图1部分,非黑色部分不透。解决办法就是增加掩图(图2),掩图白色区域对于图3黑色区域,黑色其余对应图3非黑色区域
#include "header.h"
bool masking=TRUE;
bool scene;
GLuint texture[5];
GLuint loop;
GLfloat roll;
AUX_RGBImageRec *LoadBMP(char *Filename)
{
FILE *File=NULL;
if (!Filename)
{
return NULL;
}
File=fopen(Filename,"r");
if (File)
{
fclose(File);
return auxDIBImageLoad(Filename);
}
return NULL;
}
int LoadGLTextures()
{
int Status=FALSE;
AUX_RGBImageRec *TextureImage[5];
memset(TextureImage,0,sizeof(void *)*5);
if ((TextureImage[0]=LoadBMP("Data/logo.bmp")) &&
(TextureImage[1]=LoadBMP("Data/mask1.bmp")) &&
(TextureImage[2]=LoadBMP("Data/image1.bmp")) &&
(TextureImage[3]=LoadBMP("Data/mask2.bmp")) &&
(TextureImage[4]=LoadBMP("Data/image2.bmp")))
{
Status=TRUE;
glGenTextures(5, &texture[0]);
for (loop=0; loop<5; loop++)
{
glBindTexture(GL_TEXTURE_2D, texture[loop]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);
}
}
for (loop=0; loop<5; loop++)
{
if (TextureImage[loop])
{
if (TextureImage[loop]->data)
{
free(TextureImage[loop]->data);
}
free(TextureImage[loop]);
}
}
return Status;
}
GLvoid ReSizeGLScene(GLsizei width, GLsizei height)
{
if (height==0)
{
height=1;
}
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
int InitGL(void)
{
if (!LoadGLTextures())
{
return FALSE;
}
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_TEXTURE_2D);
return TRUE;
}
void DrawGLScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f,0.0f,-2.0f);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, -roll+0.0f); glVertex3f(-1.1f, -1.1f, 0.0f);
glTexCoord2f(3.0f, -roll+0.0f); glVertex3f( 1.1f, -1.1f, 0.0f);
glTexCoord2f(3.0f, -roll+3.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
glTexCoord2f(0.0f, -roll+3.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
glEnd();
glEnable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
if (masking)
{
glBlendFunc(GL_DST_COLOR,GL_ZERO);
}
if (scene)
{
glTranslatef(0.0f,0.0f,-1.0f);
glRotatef(roll*360,0.0f,0.0f,1.0f);
if (masking)
{
glBindTexture(GL_TEXTURE_2D, texture[3]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
glEnd();
}
glBlendFunc(GL_ONE, GL_ONE);
glBindTexture(GL_TEXTURE_2D, texture[4]);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
glEnd();
}
else
{
if (masking)
{
glBindTexture(GL_TEXTURE_2D, texture[1]);
glBegin(GL_QUADS);
glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f);
glTexCoord2f(roll+4.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f);
glTexCoord2f(roll+4.0f, 4.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
glTexCoord2f(roll+0.0f, 4.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
glEnd();
}
glBlendFunc(GL_ONE, GL_ONE);
glBindTexture(GL_TEXTURE_2D, texture[2]);
glBegin(GL_QUADS);
glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f);
glTexCoord2f(roll+4.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f);
glTexCoord2f(roll+4.0f, 4.0f); glVertex3f( 1.1f, 1.1f, 0.0f);
glTexCoord2f(roll+0.0f, 4.0f); glVertex3f(-1.1f, 1.1f, 0.0f);
glEnd();
}
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glFlush();
}
void rotate()
{
roll+=0.002f;
if (roll>1.0f)
{
roll-=1.0f;
}
glutPostRedisplay();
}
void mouse(int button,int state,int x,int y)
{
switch(button)
{
case GLUT_LEFT_BUTTON:
if(GLUT_DOWN==state)
{
glutIdleFunc(rotate);
}
break;
case GLUT_RIGHT_BUTTON:
if(GLUT_DOWN==state)
{
//glutIdleFunc(0);
}
break;
}
}
void keyboard(unsigned char key,int x,int y)
{
switch (key)
{
case 'M':
masking=true;
break;
case 'm':
masking=false;
break;
case 'S':
scene=true;
break;
case 's':
scene=false;
break;
}
glutPostRedisplay();
}
int main(int argc,char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB|GLUT_DEPTH);
glutInitWindowSize(800,600);
glutInitWindowPosition(100,100);
glutCreateWindow("蒙版");
InitGL();
glutDisplayFunc(DrawGLScene);
glutKeyboardFunc(keyboard);
glutMouseFunc(mouse);
glutReshapeFunc(ReSizeGLScene);
glutMainLoop();
}