OpenGLES glBlendFunc 的使用

本文介绍了OpenGL中的颜色混合方法,特别是glBlendFunc的使用。通过设置源因子和目标因子,实现源色与底色的混合,用于创建半透明效果。以GL_SRC_ALPHA和GL_ONE_MINUS_SRC_ALPHA为例,解释了如何计算混合颜色值,并强调了混合顺序对结果的影响。

OpenGLES glBlendFunc 的使用

在OpenGL里做颜色混合一般有两种方式,一种是将要混合的纹理都传入Fragment Shader,在shader里实现算法完成混合,一种就是利用OpenGL渲染管线最后的blending阶段自动对源色和底色进行混合。

在Fragment Shader手动实现混合算法比较自由,我们可以自定义一些混合方法,实现一些OpenGL自带混合模式无法实现的复杂混合算法,缺点是在部分GPU上同一个texture无法既作FBO输出,又作纹理采样输入,如果底图作为输入传入Fragment Shader,则当前FBO需要绑定另一个texture作为输出,否则会出现黑色和黑块的兼容性问题。如果混合区域覆盖全图,可以用FBO绑定一个空的texture作为输出,同时原始底图传入Fragment Shader作为输入;如果混合区域只占全图的一部分,那么就需要首先复制一份底图纹理并绑定到FBO作为输出,同时原始底图纹理传入Fragment Shader做混合,这两种不同的混合场景下,不管混合区域是全图还是部分区域,都需要申请一块额外的底图大小的纹理存储(空白或复制底图),另外部分区域混合时还需要一次额外的渲染(复制底图),混合所需要的空间和时间都有额外开销。

作为对比,OpenGL渲染管线自带的混合模式包含的混合算法是有限的,不过基本可以满足大部分的使用场景。优点是渲染时不用将底图作为采样纹理输入,定义好混合模式后,在Fragment Shader里只需要对源图纹理进行采样,然后由OpenGL驱动自动完成混合算法。这种方法对全图和部分区域的混合同样适用,都不用额外申请纹理存储空间,渲染时不用切换FBO,只需渲染一次,渲染的效率比在Fragment Shader里手动实现混合算法要高。

OpenGL渲染管线的最后阶段会将源色和底色进行混合。这里的源色和底色分别指什么呢?我们可以把OpenGL的一次渲染过程形象地比作画家拿画笔在画布上作画,假如画家拿着黄色的画笔在红色的画布上作画,最后画出一幅绿色的图,这里画笔的黄色就是源色,画布上的红色就是底色,又叫目标色,绿色就是混合以后的结果。对应到OpenGL的一次渲染过程里,源色就是Fragment Shader处理结束后给gl_FragColor的赋值,底色就是当前FBO绑定的纹理的颜色值,混合后的结果会更新底色纹理的颜色值,就好比是红色的画布在用黄色的笔画完后变成了绿色,绿色变成了画布新的颜色。OpenGL里的混合就是将源色和底色以某种方式自动混合的技术,通常用来绘制半透明物体(不透明物体颜色直接覆盖,无需混合)。不同的混合模式算法其实就是定义了源色和底色不同的混合比例,最后达到不同程度的混合效果。需要注意的是,物体的绘制顺序可能会影响到OpenGL混合的最终处理效果

下面用数学公式来表达一下这个运算方式。假设源颜色的四个分量(指红色,绿色,蓝色,alpha值)是(Rs, Gs, Bs, As),目标颜色的四个分量是(Rd, Gd, Bd, Ad),又设源因子为(Sr, Sg, Sb, Sa),目标因子为(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_DST_ALPHA( Ad , Ad , Ad , Ad )
GL_DST_COLOR( Rd , Gd , Bd , Ad )
GL_ONE(1,1,1,1)
GL_ONE_MINUS_DST_ALPHA(1,1,1,1) - (Ad,Ad,Ad,Ad)
GL_ONE_MINUS_DST_COLOR(1,1,1,1) - (Rd,Gd,Bd,Ad)
GL_ONE_MINUS_SRC_ALPHA(1,1,1,1) - (As,As,As,As)
GL_SRC_ALPHA( As , As , As , As )
GL_SRC_ALPHA_SATURATE(f,f,f,1) : f = min(As,1-Ad)
GL_ZERO(0 , 0 , 0 , 0 )

我们举个例子来说明混合颜色值是怎么算出来的。以最常用的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 , 0.72 , 0.64 , 0.56 ) + ( 0.12 , 0.1 , 0.08 , 0.06 ) = ( 0.92 , 0.82 , 0.72 , 0.62 )。

使用这种混合参数的意义也很明显,源色的alpha值决定了结果颜色中源色和目标色的百分比。这里源色的alpha值为0.8,即结果颜色中源色占80%,目标色占20%

源代码

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值