OpenGL编程指南14:混合半透明Blend

来源:互联网 发布:linux命令行删除文件 编辑:程序博客网 时间:2024/05/29 03:25

1.混合2D

Blend 混合是将源色和目标色以某种方式混合生成特效的技术。混合常用来绘制透明或半透明的物体。在混合中起关键作用的α值实际上是将源色和目标色按给定比率进行混合,以达到不同程度的透明。α值为0则完全透明,α值为1则完全不透明。混合操作只能在RGBA模式下进行,颜色索引模式下无法指定α值。物体的绘制顺序会影响到OpenGL的混合处理。

glEnable( GL_BLEND );   // 启用混合
glDisable( GL_BLEND );  // 禁用关闭混合

glBlendFunc( GLenum sfactor , GLenum dfactor );  // 混合函数
sfactor 源混合因子
dfactor 目标混合因子

glBlendFunc( GL_ONE , GL_ZERO );        // 源色将覆盖目标色
glBlendFunc( GL_ZERO , GL_ONE );        // 目标色将覆盖源色
glBlendFunc( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ); // 是最常使用的

例如:

若源色为 ( 1.0 , 0.9 , 0.7 , 0.8 )。源色使用 GL_SRC_ALPHA即 0.8*1.0 , 0.8*0.9 , 0.8*0.8 , 0.8*0.7结果为 0.8 , 0.72 , 0.64 , 0.56
目标色为 ( 0.6 , 0.5 , 0.4 , 0.3 )。目标色使用GL_ONE_MINUS_SRC_ALPHA即 1 - 0.8 = 0.2  0.2*0.6 , 0.2*0.5 , 0.2*0.4 , 0.2*0.3结果为 0.12 , 0.1 , 0.08 , 0.06
由此而见,使用这个混合函数,源色的α值决定了结果颜色的百分比。
这里源色的α值为0.8,即结果颜色中源色占80%,目标色占20%。

2.混合3D

混合3D物体时,基本原理和混合2D物体一样,但需要将深度检测关闭或设置为只读
因为深度检测会剔除被遮挡的部分物体。
glEnable( GL_DEPTH_TEST );          // 启用深度缓存
glDisable( GL_DEPTH_TEST );         // 禁用深度缓存
glDepthMask( GL_FALSE );            // 深度缓存为 只读
glDepthMask( GL_TRUE );             // 深度缓存为 读/写

按以下步骤,可以在 3D 场景中使用混合和深度检测
1、使用深度检测
2、绘制不透明的物体
3、设只读 深度检测
4、绘制半透明的物体
5、设 读/写 深度检测

3.编程实践

#include <GL/glut.h>#include <stdlib.h>static int leftFirst = GL_TRUE;static void init(void){   glEnable (GL_BLEND);   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   //glBlendFunc(GL_ONE, GL_ONE);   //禁用混合功能   glShadeModel (GL_FLAT);   glClearColor (0.0, 0.0, 0.0, 0.0);}static void drawLeftTriangle(void){   glBegin (GL_TRIANGLES);      glColor4f(1.0, 0.0, 0.0, 0.55);      glVertex3f(0.1, 0.9, 0.0);       glVertex3f(0.1, 0.1, 0.0);       glVertex3f(0.7, 0.5, 0.0);    glEnd();}static void drawRightTriangle(void){   glBegin (GL_TRIANGLES);      glColor4f(0.0, 1.0, 0.0, 0.55);      glVertex3f(0.9, 0.9, 0.0);       glVertex3f(0.3, 0.5, 0.0);       glVertex3f(0.9, 0.1, 0.0);    glEnd();}void display(void){   glClear(GL_COLOR_BUFFER_BIT);   if (leftFirst) {      drawLeftTriangle();      drawRightTriangle();   }   else {      drawRightTriangle();      drawLeftTriangle();   }   glFlush();}void reshape(int w, int h){   glViewport(0, 0, (GLsizei) w, (GLsizei) h);   glMatrixMode(GL_PROJECTION);   glLoadIdentity();   if (w <= h)       gluOrtho2D (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w);   else       gluOrtho2D (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0);}void keyboard(unsigned char key, int x, int y){   switch (key) {      case 't':case 'T':         leftFirst = !leftFirst;         glutPostRedisplay();             break;      default:         break;   }}int main(int argc, char** argv){   glutInit(&argc, argv);   glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);   glutInitWindowSize (200, 200);   glutCreateWindow (argv[0]);   init();   glutReshapeFunc (reshape);   glutKeyboardFunc(keyboard);   glutDisplayFunc (display);   glutMainLoop();   return 0;}

输出结果如下:

   

左图为关闭“Blend”结果。右图为开启“Blend”结果。

0 0