Android图像处理系列:OpenGL混合模式的使用

本文探讨了OpenGL渲染管线中的混合模式,讲解如何在Android平台上使用OpenGL进行混合,包括Bitmap解码时不预乘和混合时不再乘以alpha值的处理方式,以及混合模式在3D渲染中的影响和解决遮挡问题的策略。

OpenGL一次渲染过程包含了多个阶段,包括顶点着色器、图元组装、栅格化、片元着色器、测试和混合等,最后将结果输出的FrameBuffer上。渲染管线最后一个阶段就是混合。
混合模式0.png
混合是在绘制时,不是直接把新的颜色覆盖在原来旧的颜色上,而是将新的颜色与旧的颜色经过一定的运算,从而产生新的颜色。新的颜色称为源颜色,原来旧的颜色称为目标颜色。传统意义上的混合,是将源颜色乘以源因子,目标颜色乘以目标因子,然后相加。

在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渲染管线自带的混合模式的用法和实例,同时简要介绍一下天天P图里用到的一些混合算法及效果,以及3D渲染时使用混合模式需要注意的一些问题。

OpenGL中的混合模式

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

OpenGL API提供了相关接口来开启/关闭混合模式以及设置源色和底色混合因子,以Android Java层系统接口为例,相关调用如下:

GLES20.glEnable
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值