• 理论基础
    混合:主要就是用来做一些如透明的特效,其实就是源颜色与目标颜色进行混合计算得到一个新颜色的过程。混合发生在图元光栅化之后,片段写入帧缓冲之前,片段与对应位置的帧缓冲区像素进行互操作形成新的像素颜色的过程及时混合。需要通过glEnable(GL_BLEND)来激活混合功能,否则的话片段直接覆盖对应像素。颜色的alpha分量值此时就会发挥作用。
    默认混合计算得到的新颜色是:

注释:
1,先写入帧缓冲的是目标颜色,后将要写入的是源颜色,与它们的深度值大小无关。
2,openGL渲染时,将颜色值放在颜色缓冲区中,将深度值放在深度缓冲区中,如果深度测试关闭时,新的颜色值就会简单的覆盖颜色缓冲区中原来的值,而如果深度测试开启时,只有新的颜色深度值大于原来的值时才被覆盖。所以一般情况下颜色值要么完全覆盖要么完全丢弃。而如果同时又开启了混合,那么片段值就不能随便丢弃或覆盖了,这时主要就是要注意绘制的顺序,而如果这个绘制顺序很难确定,可以用glDepthMask(GL_FALSE)设置深度缓冲区为只读状态,这样来限制受深度测试的影响。
3,绘制顺序:对于半透明的,要先画远,再画近。对于不透明的,因为有深度测试,顺序不影响最终效果。但要优化性能的话,一般是先画近,再画远(直接丢弃而不需要覆盖)。苹果手机的显卡,对于不透明的,关闭混合之后,可以不论远近,性能一样。


  • 实例代码
    1,背景颜色与几何物体颜色做基本混合
#include "GLTools.h"
#include "GLShaderManager.h"#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endifvoid init(void)
{glClearColor(1.0, 1.0, 0.0, 0.0);glBlendFunc(GL_ONE, GL_ONE);//设置源因子与目标因子取值glEnable(GL_BLEND);//开启混合
}void display(void)
{glClear(GL_COLOR_BUFFER_BIT);//这个方形与背景混合glColor3f(0.0, 0.0, 1.0);glRectf(-0.5,-0.5,0.5,0.5);glFlush();
}void reshape(int w, int h)
{GLdouble aspect = (GLdouble) w / h;glViewport(0, 0, (GLsizei) w, (GLsizei) h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (aspect < 1.0) {aspect = 1.0 / aspect;glOrtho(-aspect, aspect, -1.0, 1.0, -1.0, 1.0);} elseglOrtho(-1.0, 1.0, -aspect, aspect, -1.0, 1.0);glMatrixMode(GL_MODELVIEW);
}void keyboard(unsigned char key, int x, int y)
{//设置混合的计算方式switch (key) {case 'a': case 'A'://源颜色+目标颜色(默认形式)glBlendEquation(GL_FUNC_ADD);break;case 's': case 'S'://源颜色-目标颜色glBlendEquation(GL_FUNC_SUBTRACT);break;case 'r': case 'R'://目标颜色-源颜色glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);break;case 'm': case 'M'://分别取目标颜色和源颜色rgba中较小的值glBlendEquation(GL_MIN);break;case 'x': case 'X'://分别取目标颜色和源颜色rgba中较大的值glBlendEquation(GL_MAX);break;case 27:exit(0);}glutPostRedisplay();
}int main(int argc, char** argv)
{glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);glutInitWindowSize(512,512);glutInitWindowPosition(100, 100);glutCreateWindow(argv[0]);init();glewInit();glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutDisplayFunc(display);glutMainLoop();return 0;}

2,利用混合做遮挡透明

#include "GLTools.h"
#include "GLShaderManager.h"#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endifstatic int leftFirst = GL_TRUE;static void init(void)
{glEnable (GL_BLEND);glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);glShadeModel (GL_FLAT);glClearColor (0.0, 0.0, 0.0, 0.0);
}static void drawLeftTriangle(void)
{glBegin (GL_TRIANGLES);glColor4f(1.0, 1.0, 0.0, 0.75);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, 1.0, 0.75);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);elsegluOrtho2D (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;case 27:  /*  Escape key  */exit(0);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;
}

3,使用深度缓冲区进行三维混合(主要是使用glDepthMask来控制不让深度测试丢弃遮挡部分颜色值,然后就可以和基本操作一样进行混合)

#include "GLTools.h"
#include "GLShaderManager.h"#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif#define MAXZ 8.0
#define MINZ -8.0
#define ZINC 0.4static float solidZ = MAXZ;
static float transparentZ = MINZ;
static GLuint sphereList, cubeList;static void init(void)
{GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 0.15 };GLfloat mat_shininess[] = { 100.0 };GLfloat position[] = { 0.5, 0.5, 1.0, 0.0 };glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);glLightfv(GL_LIGHT0, GL_POSITION, position);glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glEnable(GL_DEPTH_TEST);//使用显示列表绘制球体sphereList = glGenLists(1);glNewList(sphereList, GL_COMPILE);glutSolidSphere (0.4, 16, 16);glEndList();//使用显示列表绘制立方体cubeList = glGenLists(1);glNewList(cubeList, GL_COMPILE);glutSolidCube (0.6);glEndList();
}void display(void)
{GLfloat mat_solid[] = { 0.75, 0.75, 0.0, 1.0 };GLfloat mat_zero[] = { 0.0, 0.0, 0.0, 1.0 };GLfloat mat_transparent[] = { 0.0, 0.8, 0.8, 0.6 };GLfloat mat_emission[] = { 0.0, 0.3, 0.3, 0.6 };glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glPushMatrix ();glTranslatef (-0.15, -0.15, solidZ);glMaterialfv(GL_FRONT, GL_EMISSION, mat_zero);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_solid);glCallList (sphereList);glPopMatrix ();glPushMatrix ();glTranslatef (0.15, 0.15, transparentZ);glRotatef (15.0, 1.0, 1.0, 0.0);glRotatef (30.0, 0.0, 1.0, 0.0);glMaterialfv(GL_FRONT, GL_EMISSION, mat_emission);glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_transparent);glEnable (GL_BLEND);glDepthMask (GL_FALSE);//设置深度缓冲区只读(目的是不让它丢弃遮挡部分)glBlendFunc (GL_SRC_ALPHA, GL_ONE);glCallList (cubeList);glDepthMask (GL_TRUE);//恢复深度缓冲区读写glDisable (GL_BLEND);glPopMatrix ();glutSwapBuffers();
}void reshape(int w, int h)
{glViewport(0, 0, (GLint) w, (GLint) h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h)glOrtho (-1.5, 1.5, -1.5*(GLfloat)h/(GLfloat)w,1.5*(GLfloat)h/(GLfloat)w, -10.0, 10.0);elseglOrtho (-1.5*(GLfloat)w/(GLfloat)h,1.5*(GLfloat)w/(GLfloat)h, -1.5, 1.5, -10.0, 10.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();
}void animate(void)
{if (solidZ <= MINZ || transparentZ >= MAXZ)glutIdleFunc(NULL);else {solidZ -= ZINC;transparentZ += ZINC;glutPostRedisplay();}
}void keyboard(unsigned char key, int x, int y)
{switch (key) {case 'a':case 'A':solidZ = MAXZ;transparentZ = MINZ;glutIdleFunc(animate);break;case 'r':case 'R':solidZ = MAXZ;transparentZ = MINZ;glutPostRedisplay();break;case 27:exit(0);}
}int main(int argc, char** argv)
{glutInit(&argc, argv);glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);glutInitWindowSize(500, 500);glutCreateWindow(argv[0]);init();glutReshapeFunc(reshape);glutKeyboardFunc(keyboard);glutDisplayFunc(display);glutMainLoop();return 0;
}

OpenGL--混合相关推荐

  1. OpenGL混合功能实例

    OpenGL 混合功能实例 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <sb7.h> #include <vmath.h& ...

  2. OpenGL 混合Blending

    OpenGL混合Blending 混合Blending简介 丢弃片段 混合 渲染半透明纹理 不要打乱顺序 混合Blending简介 OpenGL中,混合(Blending)通常是实现物体透明度(Tra ...

  3. Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染

    Qt移动应用开发(八):实现跨平台的QML和OpenGL混合渲染 上一篇文章讲到了利用C++这个桥梁,我们实现了QML和Java的交互.Qt 5大力推崇的QML/JS开发,让轻量.高速开发的QML/J ...

  4. qt opengl 混合实现半透明

    在二维绘图里面的半透明很简单,把alpha通道的值不设置为1或者255就能看见后面的物体:后面物体的清晰度根据设置值的大小来决定.而在opengl中要实现半透明效果也很简单,但相比二维绘图还是要麻烦一 ...

  5. 11、OpenGL - 混合(颜色混合)

    混合 OpenGL 渲染时会把颜色存在颜色缓冲区中,每个片段的深度值也是放在深度缓冲区. 当深度缓冲区被关闭时,新的颜色将简单的覆盖原来颜色缓冲区存在的颜色值. 当深度缓冲区再次打开时,新的颜色片段只 ...

  6. OpenGL: 混合

    OpenGL 红宝书 混合 6.1 混合 6.1.1 源因子和目标因子 假定源和目标混合因子分别为(Sr, Sg, Sb, Sa)和(Dr,Dg,Db,Da), 混合后的RGB值如下: (RsSr + ...

  7. Simens NX(原UG)与OpenGL混合开发 /Program with NX and OpenGL

    关于 NX3.0跟随点窗口的方法研究 作者:xusir98 程序主要过程 : 1. 找出 NX 视图的显示窗口 2. HOOK NX 视图的鼠标操作 3. 在 HOOK 的回调函数中利用 OPENGL ...

  8. qt android opengl,案例:实现Qt和OpenGL混合渲染 | 求索阁

    Qt自有一个绘图的引擎,这个引擎的核心就是QPainter,我们知道QPainter在渲染二维图形和文字有很大的优势,而OpenGL是当前流行的三维渲染器,怎样才能将两者结合起来,制作更为丰富的应用程 ...

  9. opengl 反走样 混合 多重采样 blend multisample

    1. 反走样         在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观.这是因为直线.多边形.色彩边界等是连续的,而光栅则是由离散的点组成,在光栅显示 ...

  10. OpenGL入门学习(十二) 【转】

    片断测试其实就是测试每一个像素,只有通过测试的像素才会被绘制,没有通过测试的像素则不进行绘制.OpenGL提供了多种测试操作,利用这些操作可以实现一些特殊的效果. 我们在前面的课程中,曾经提到了&qu ...

最新文章

  1. 微信小程序之wx:if视图层的条件渲染
  2. ASP.NET 自定义项目模板
  3. cassandra_Apache Cassandra和低延迟应用程序
  4. Ajax知识笔记——入门,同步和异步,XHR
  5. 【转】[技术回顾系列]--WebService事务处理
  6. Struts学习笔记--导航
  7. Django Model出现的中文问题
  8. python3 自动识图
  9. win2003 ent 64 + mssql ent 64
  10. Sailfish预研结果
  11. SqliteDev如何突破限制
  12. Wincc声音报警简单方法
  13. 基于Ubuntu虚拟机的Linux驱动开发入门
  14. sql中取字符串长度的函数
  15. 计算机图形学(闫令琪博士课程答疑)-Shading(二)
  16. 彻底搞懂单例模式的懒汉式饿汉式 双检索 线程安全问题
  17. 计算机维护与维修方法,浅谈计算机维护与维修方法
  18. htc Vive中VR界面闪烁的解决
  19. 你真的了解整流桥的结构和原理吗?
  20. 全国最搞笑的名字都在这了,看了不准笑!

热门文章

  1. 《傻瓜计量经济学与stata应用》第二章do文件,记得把数据考到当前目录或带上路径,否则可能无法打开
  2. Retrofit+OKHttp+RxJava的使用
  3. 怎么在Excel中查找指定文本并标记颜色
  4. 爆笑!史上最强的中国式英语
  5. 体验新一代Windows CE: Windows Embedded Compact 7
  6. 基于Java毕业设计校园外卖系统Web端源码+系统+mysql+lw文档+部署软件
  7. 华为手机大变?余承东被传离职转岗,进军美国受阻惹的祸?
  8. 【导航链接】计算机科研学习
  9. 工作十年的数据分析师被炒,没有方向,你根本躲不过中年危机
  10. 【信号去噪】基于蚁群算法优化小波阈值实现信号去噪附matlab代码