OpenGL-入门-二维混合

glEnable(GL_BLEND);//开启 OpenGL 的混合
glDisable(GL_BLEND);//关闭 OpenGL 的混合

glBlendFunc(源因子,标因子);

混合是什么呢?

混合就是把两种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种 方式混在一起,从而实现特殊的效果。
假设我们需要绘制这样一个场景:透过红色的玻璃去看绿色的物体,那么可以先绘制绿色的物体,再绘制红色玻璃。在绘制 红色玻璃的时候,利用“混合”功能,把将要绘制上去的红色和原来的绿色进行混合,于是得到一种新的颜色,看上去就好像 玻璃是半透明的。
要使用 OpenGL 的混合功能,只需要调用:glEnable(GL_BLEND);即可。
要关闭 OpenGL 的混合功能,只需要调用:glDisable(GL_BLEND);即可。
注意:只有在 RGBA 模式下,才可以使用混合功能,颜色索引模式下是无法使用混合功能的。混合是什么呢?混合就是把两 种颜色混在一起。具体一点,就是把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊 的效果。

一、源因子和目标因子

前面我们已经提到,混合需要把原来的颜色和将要画上去的颜色找出来,经过某种方式处理后得到一种新的颜色。这里把将要画上去的颜色称为“源颜色”,把原来的颜色称为“目标颜色”。
  对应源颜色乘对应“源因子”的结果,与对应目标颜色乘对应 “目标因子”的结果,经过运算,得到新的颜色。
   用数学公式来表达一下这个运算方式,假设:
   源颜色的四个分量(指红色,绿色,蓝色,alpha 值)是(Rs, Gs, Bs, As),设源因子为(Sr, Sg, Sb, Sa);
   目标颜色的四个分量是(Rd, Gd, Bd, Ad),设目标因子为(Dr, Dg, Db, Da)。
   则混合产生的新颜色可以表示为: (Rs*Sr+Rd*Dr, Gs*Sg+Gd*Dg, Bs*Sb+Bd*Db, As*Sa+Ad*Da)
   当然了,如果颜色的某一分量超过了 1.0,则它会被自动截取为 1.0,不需要考虑越界的问题。
   注意: 所谓源颜色和目标颜色,是跟绘制的顺序有关。假如先绘制了一个红色的物体,再在其上绘制绿色的物体。则绿色是源颜色,红色是目标颜色。如果顺序反过来,则红色就是源颜色,绿色才是目标颜色。在绘制时,应该注意顺序,使得绘制的源颜色与设置的源因子对应,目标颜色与设置的目标因子对应。
  
  源因子和目标因子是可以通过 glBlendFunc 函数来进行设置的。glBlendFunc 有两个参数,前者表示源因子,后者表示目 标因子。这两个参数可以是多种值,下面介绍比较常用的几种。
  GL_ZERO:表示使用 0.0 作为因子,实际上相当于不使用这种颜色参与混合运算。
   GL_ONE:表示使用 1.0 作为因子,实际上相当于完全的使用了这种颜色参与混合运算。
  GL_SRC_ALPHA:表示使用源颜色的 alpha 值来作为因子。 GL_DST_ALPHA:表示使用目标颜色的 alpha 值来作为因子。
  GL_ONE_MINUS_SRC_ALPHA:表示用 1.0 减去源颜色的 alpha 值来作为因子。   GL_ONE_MINUS_DST_ALPHA:表示用 1.0 减去目标颜色的 alpha 值来作为因子。

举例来说:二维混合

#include "pch.h"
#include <GL/glut.h>

void myDisplay(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	
	glEnable(GL_BLEND);
	glBlendFunc(GL_ONE, GL_ZERO);
	//glBlendFunc(GL_ZERO, GL_ONE);
	//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//glBlendFunc(GL_ONE, GL_ONE);
	glColor4f(1, 0, 0, 0.5);
	glRectf(-1, -1, 0.5, 0.5);
	glColor4f(0, 1, 0, 0.5);
	glRectf(-0.5, -0.5, 1, 1);

	glutSwapBuffers();
	glFlush();/*,保证前面的 OpenGL 命令立即执行(而不是让它们在缓冲区中等待)。其作用跟 fflush(stdout)类似。 */
}

int main(int argc,char *argv[])
{
	glutInit(&argc,argv);		/*、glutInit,对 GLUT 进行初始化,这个函数必须在其它的 GLUT 使用之前调用一次。 */
	glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE);	/*设置显示方式,GLUT_RGB 表示使用 RGB 颜色,
													 与之对应的还有 GLUT_INDEX(表示 使用索引颜色)。
													 GLUT_SINGLE 表示使用单缓冲,
													 与之对应的还有 GLUT_DOUBLE(使用双缓冲)。*/
	glutInitWindowPosition(100, 100);	/*设置窗口在屏幕中的位置*/
	glutInitWindowSize(400, 400);		/*设置窗口的大小*/
	glutCreateWindow("混合");			/*根据前面设置的信息创建窗口。参数将被作为窗口的标题。
					注意:窗口被创建后,并不立即显示到屏幕上。需要调用 glutMainLoop 才能看到窗口。*/
	glutDisplayFunc(&myDisplay);
	glutMainLoop();		 /*进行一个消息循环*/
	return 0;
}

如果设置了 glBlendFunc(GL_ONE, GL_ZERO);,则表示完全使用源颜色,完全不使用目标颜色,因此画面效果和不使用混合的时候一致(当然效率可能会低一点点)。如果没有设置源因子和目标因子,则默认情况就是这样的设置。
在这里插入图片描述

如果设置了 glBlendFunc(GL_ZERO, GL_ONE);,则表示完全不使用源颜色,因此无论你想画什么,最后都不会被画上去 了。(但这并不是说这样设置就没有用,有些时候可能有特殊用途)
在这里插入图片描述

如果设置了glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);,则表示源颜色乘以自身的 alpha 值,目标 颜色乘以 1.0 减去源颜色的 alpha 值,这样一来,源颜色的 alpha 值越大,则产生的新颜色中源颜色所占比例就越大,而目标颜色所占比例则减小。这种情况下,我们可以简单的将源颜色的 alpha 值理解为“不透明度”。这也是混合时最常用的方式。
在这里插入图片描述
  如果设置了 glBlendFunc(GL_ONE, GL_ONE);,则表示完全使用源颜色和目标颜色,最终的颜色实际上就是两种颜色的简 单相加。例如红色(1, 0, 0)和绿色(0, 1, 0)相加得到(1, 1, 0),结果为黄色。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42785489/article/details/89766256
今日推荐