大家好,这是我的OpenGL ES
高级进阶系列文章,在我的github
上有一个与本系列文章对应的项目,欢迎关注,链接:github.com/kenneycode/…
今天给大家介绍OpenGL
的颜色混合,什么是颜色混合呢?颜色混合就是把两种颜色按某种规则混合起来得到新的颜色,来看一张图:
比如我们两种颜色颜色,一种是纯蓝色ARGB(255, 0, 0, 255)
,一种是纯绿色ARGB(255, 0, 255, 0)
,混合时分别各取一半,就得到了混合后的颜色ARGB(255, 0, 127, 127)
,这就是颜色合混的基本概念。
那么什么时候需要用到颜色混合?我们来看一种最常见的情况,我们把一张带有透明部分的纹理渲染到另一张纹理上,会怎样?
大家可能会说,这不是很显然吗?透明部分会把底图透出来,但如果你在OpenGL
里不使用颜色混合直接渲染,你会发现结果是这样的:
透明部分并没有把底图透出来,这是为什么呢?因为颜色混合默认是关闭的,当没开启颜色混合时,把一个颜色渲染到另一个颜色上,新的颜色就会把原颜色完全覆盖,从而得到一个alpha
为0的颜色,透出了最底层的黑色。
我们来看看如何用颜色混合来解决这个问题,首先需要开启颜色混合:
// 启用颜色混合
// Enable color blend
GLES30.glEnable(GLES30.GL_BLEND)
还需要设置混合方式,所谓混合方式的就是指定源颜色(将要渲染的颜色)和目标颜色(已经存在的底图颜色)以何种方式进行混合,例如文章开篇时,以源颜色和目标颜色各占0.5的方式进行混合,用式子来表示就是:
混合后颜色 = 源颜色 * 源因子 + 目标颜色 * 目标因子
OpenGL
内置了多种混合方式,通过glBlendFunc()
来设置,第一个参数是设置源因子,第二个参数是设置目标因子,在这里,我们需要这样设置:
// 设置混合方式
// Set blend functions
GLES30.glBlendFunc(GLES30.GL_SRC_ALPHA, GLES30.GL_ONE_MINUS_SRC_ALPHA)
GL_SRC_ALPHA
表示取源颜色的alpha
值作为因子,GL_ONE_MINUS_SRC_ALPHA
表示取1减去源颜色的alpha
值作为因子,这样能得到什么效果呢?
先来看看源颜色的透明部分和目标颜色(底图颜色)的不透明部分混合,假设我们的目标颜色是ARGB_DST=(1.0, a, b, c)
,源颜色是ARGB_SRC=(0.0, d, e, f)
此时:
混合后颜色 = ARGB_SRC * 0.0 + ARGB_DST * (1.0 - 0.0) = ARGB_DST
再来看看源颜色的不透明部分和目标颜色(底图颜色)的不透明部分混合,假设我们的目标颜色是ARGB_DST=(1.0, a, b, c)
,源颜色是ARGB_SRC=(1.0, d, e, f)
此时:
混合后颜色 = ARGB_SRC * 1.0 + ARGB_DST * (1.0 - 1.0) = ARGB_SRC
因此效果就是,源图中的透明部分,渲染后的颜色完全是底图颜色,等于透出了底图,源图中的不透明部分,渲染之后的颜色完全是源图的颜色:
这样就得到了正确的效果。
我们再来试试GL_ONE
:
GLES30.glBlendFunc(GLES30.GL_ONE, GLES30.GL_ONE)
这样就是
混合后颜色 = ARGB_SRC * 1.0 + ARGB_DST * 1.0
来看效果:
还有很多种混合方式可以设置,具体可以查询官方文档:www.khronos.org/registry/Op…
用glBlendFunc
设置的混合因子会同时作用于RGBA
四个通道上,我们还可以将A通道和RGB通道设置不同的混合因子:
void glBlendFuncSeparate(
GLenum srcRGB,
GLenum dstRGB,
GLenum srcAlpha,
GLenum dstAlpha
)
有时内置的混合方式有时候并不能满足我们的要求,例如要实现:
混合后颜色 = 源颜色 * 0.123 + 目标颜色 * 0.877
这时用内置的混合方式就不能实现,因为混合因子不能任意设置,这时可以自己在fragment shader
中实现。
代码在我github
的OpenGLESPro
项目中,本文对应的是SampleColorBlend
,项目链接:[github.com/kenneycode/…github.com/kenneycode/…
感谢阅读!