openGL中的混合

    之前在项目中就使用过混合,但是研究的不深入,近期美术的一个需求让我下决心重新深入的研究了一下混合以及它在cocos2d-x中的使用,在这里分享给大家。

混合(blend,有些翻译书上把它称作混融,以下简称混合),在openGL中,当一个输入的片元通过了所有相关的片元测试,就可以在与颜色缓存中当前的内容通过某种方式进行合并了。最简单的,也是默认的方式,就是直接覆盖已有的值,实际上不能称作是合并。除此之外,我们也可以将帧缓存中已有的颜色与输入的片元颜色进行混合。这是在openGL流程上的定义,从绘制图片的角度说,其实就是上层图片的颜色和下层图片的颜色的合成方式,一般情况下,上层图片会完全覆盖下层,但是有些时候,为了实现某些效果,上下层的图片颜色会有不同的合成算法,为了实现这些颜色混合效果,不仅仅是把上下层的颜色相加减这么简单,下面设几个参数

目标色:Dc        源色:Sc

目标色系数:Ds     原色系数:Ss

关于目标色和原色系数的计算方法,一共有如下的选项:

GL_ZERO                                 (0,0,0)

GL_ONE                                   (1,1,1)

GL_SRC_COLOR                        (Rs,Gs,Bs)

GL_ONE_MINUS_SRC_COLOR     (1 - Rs,1 - Gs,1 - Bs)

GL_DST_COLOR                        (Rd,Gd,Bd)

GL_ONE_MINUS_DST_COLOR     (1 - Rd,1 - Gd,1 - Bd)

GL_SRC_ALPHA                        (As,As,As)

GL_ONE_MINUS_SRC_ALPHA     (1 - As,1 - As,1 - As)

GL_DST_ALPHA                        (Ad,Ad,Ad)

GL_ONE_MINUS_DST_ALPHA     (1 - Ad,1 - Ad,1 - Ad)

GL_SRC_ALPHA_SATURATE       (f,f,f) f=min(As,1 - Ad)

目标色和原色分别乘以系数计算后,将得到的两个值按照一定方法计算,就可以得到最后混合的颜色,计算方式包括:

GL_FUNC_ADD                          ScSs + DcDs

GL_FUNC_SUBTRACT                 ScSs - DcDs

GL_FUNC_REVERSE_SUBTRACT  DcDs - ScSs

GL_MIN                                    min(ScSs,DcDs)

GL_MAX                                   max(ScSs,DcDs)

需要说明的是,默认情况下,目标色和原色的结合采用的是 GL_FUNC_ADD的方式。

另外需要说明的是,有另外两个函数 glBlendFuncSeparate和glBlendEquationSeparate分别设置rgb色和alpha的混合方式(第一个函数设置混合参数,第二个参数设置目标色和原色的混合计算方式)

一个完整的混合流程应该包括如下的三个步骤:

//开启混合

glEnable(GL_BLEND);

//设置混合方式

glBlendEquation(GL_FUNC_ADD);

//设置混合参数生成方式

glBlendFunc(sfactor, dfactor);

首先使用glEnable设置开启混合,然后通过调用glBlendEquation设置目标色和原色的结合方式,最后调用glBlendFunc设置原色和目标色系数的生成方式。

通过下面一个例子会更加深入的理解混合,在adobe的软件中有一个效果叫滤色,滤色是混合模式,存在于颜色混合模式、通道混合模式、图层混合模式的变亮模式组中。混合后的效果类似于多个摄影幻灯片在彼此之上投影。

使用滤色和不使用滤色的效果对比:

左边是使用滤色后的混合效果。

滤色的公式是:

结果色 = 1 - (1 - 原色)* (1 - 目标色)

= 1 - (1 + 原色 * 目标色  - 原色 - 目标色)

= 原色 + 目标色 - 原色 * 目标色

= 1 * 原色  + (1 - 原色)* 目标色

原色的系数是1,目标色的系数是(1 - 原色)

得出的结论是目标色和原色的系数分别是:

blendFunc.src = GL_ONE

blendFunc.dst = GL_ONE_MINUS_SRC_COLOR

这里再分享一个使用滤色的小技巧,在lua中尤其实用,不需要直接创建一个BlendFunc,可以先从精灵中获得这个对象,然后进行修改

local blendFunc = sp:getBlendFunc()

blendFunc.src = GL_ONE

blendFunc.dst = GL_ONE_MINUS_SRC_COLOR

sp:setBlendFunc(blendFunc)

能力不足,水平有限,如有错误,欢迎指出。

时间: 2024-08-05 07:08:25

openGL中的混合的相关文章

OpenGL中的颜色混合功能(二)——抗锯齿的处理

在OpenGL中,混合功能的另一个用途是抗锯齿的处理.在绝大多数情况下,一个渲染片段映射到计算机屏幕上的一个像素.因为这些像素都是正方形的,所以通常我们可以清晰的看到两种不同颜色的分界,它们就是我们通常所说的锯齿.锯齿的出现会让人觉得图像是不自然的,极为影响观感.这种锯齿现象是计算机所产生的图像的弱点,这对于我们的许多要求尽可能逼真的渲染任务,都带来了消极的影响. 为了消除图元之间的锯齿状边缘,OpenGL使用混合功能来混合片段的颜色,也就是把像素的目标颜色与周围相邻像素的颜色进行混合.从本质上

OpenGL中的颜色混合功能(一)

我们知道,材料属性和光照参数可以极大地增加图形的逼真度,但除此之外,我们在对现实世界进行建模时,有许多效果是通过混合颜色的方式实现的.透明的物体,像是玻璃水杯,在它后面发射过来的光会与透明物体的颜色混合在一起.这种透明在OpenGL中的实现方式,是通过首先绘制背景物体,然后把前景物体(比如水杯)与颜色缓冲区中已经存在的颜色进行混合而实现的.在这一过程中,颜色的alpha值成分发挥了重要作用. 颜色的混合功能 在一般情况下,OpenGL在渲染时把颜色值存放在颜色缓冲区中,把每个片段(像素)的深度值

OpenGL中的多重采样

抗锯齿处理的最大优点之一就是它能够使多边形的边缘更为平滑,使渲染效果显得更为逼真和自然.点和直线的抗锯齿处理是得到广泛支持的,但遗憾的是,对多边形的平滑处理并没有在所有平台上都得到实现.并且,即使在可以使用GL_POLYGON_SMOOTH的时候,对整个场景进行抗锯齿处理也没有想象中的那么方便.这是因为,抗锯齿处理是基于混合操作的,这就需要从前到后对所有的图元进行排序,这是十分麻烦的. 在OpenGL中还有一个功能,称为多重采样(multisampling),可以用来解决抗锯齿处理中的这个问题.

openGL中的FBO的一个问题

前几天公司扔给我一个刚跳走的“大牛”的代码,看的实在让我捉急.逻辑非常混乱,代码模块化做的不到位,让人怀疑是否知道什么是面向对象.(应该是所有程序员看别人代码都这样的通病吧,自己的修为尚浅,也许别人看我的也是一头包,哈哈) 正题: //—————————————————————————————————————————— 在使用openGL中的fbo时,很容易遇到“二次混合”的问题.二次混合从本质上来讲是混合顺序错误. 如下图: 这是一个很让人纠结的问题.仅通过调节混合方式是不能真正地解决的.只有

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

1. 反走样         在光栅图形显示器上绘制非水平且非垂直的直线或多边形边界时,或多或少会呈现锯齿状或台阶状外观.这是因为直线.多边形.色彩边界等是连续的,而光栅则是由离散的点组成,在光栅显示设备上表现直线.多边形等,必须在离散位置采样.由于采样不充分重建后造成的信息失真,就叫走样(aliasing).而用于减少或消除这种效果的技术,就称为反走样(antialiasing). 2. OpenGL反走样的实现 OpengL中的反走样采用的是融合的技术,来实现点.线和图形的边沿以及雾和颜色和

OpenGL中实现双缓冲技术

在OpenGL中实现双缓冲技术的一种简单方法: 1.在调用glutInitDisplayMode函数时, 开启GLUT_DOUBLE,即glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);.这里将我们惯用的GLUT_SINGLE替换为GLUT_DOUBLE,意为要使用双缓冲而非单缓冲. 2. 调用glutDisplayFunc(display)注册回调函数时, 在回调函数中所有绘制操作完成后调用glutSwapBuffers()交换两个缓冲区指针. 3. 调用

什么是OpenGL中的深度、深度缓存、深度测试?

原文来自http://blog.csdn.net/xiaoquanhuang/article/details/6613705 1)直观理解 深度其实就是该象素点在3d世界中距离摄象机的距离,深度缓存中存储着每个象素点(绘制在屏幕上的)的深度值!深度测试决定了是否绘制较远的象素点(或较近的象素点),通常选用较近的,而较远优先能实现透视的效果!!! 2)Z值(深度值).Z buffer(深度缓存) 下面先讲讲Z坐标.Z坐标和X.Y坐标一样.在变换.裁减和透视除法后,Z的范围为-1.0~1.0.Dep

OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别

OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间使用.OpenGL3.0已经废弃此方法.每个glVertex与GPU进行一次通信,十分低效. glBegin(GL_TRIANGLES); glVertex(0, 0); glVertex(1, 1); glVertex(2, 2); glEnd(); 2.显示列表(glCallList) 每个gl

OpenGL中创建聚光灯的效果

现在,我们使用如下的数组来指定一个光源的位置: // 指定光源位置的数组 GLfloat lightPos[] = {0.0f, 0.0f, 75.0f, 1.0f}; // 设置光源0的位置 glLightfv(GL_LIGHT0,GL_POSITION,lightPos); lightPos数组的最后一个值在此为1.0,它表示光源的实际位置就在(X,Y,Z)所表示的位置.在默认情况下,光线从这个位置均匀地向四周发射.如果我们把lightPos数组的最后一个值设为0.0,可以使光源看上去像是来