在ClanLib中使用blend func

来源:互联网 发布:微信未备案域名分享 编辑:程序博客网 时间:2024/05/16 18:54
 
本文是对Blend Func完全没有认识的人写的,就好象一天前的我一样。
 
废话我就留到后面才说吧。在ClanLib库中的CL_Surface与CL_Sprite中都会有
这个函数:
void set_blend_func(CL_BlendFunc src, CL_BlendFunc dest);
其CL_BlendFun可以在源代码是看到定义,如下:
enum CL_BlendFunc
{
       blend_zero,                     // source or destination (0, 0, 0, 0)
       blend_one,                      // source or destination (1, 1, 1, 1)
       blend_dest_color,               // source                (Rd, Gd, Bd, Ad)
       blend_src_color,                // destination           (Rs, Gs, Bs, As)
       blend_one_minus_dest_color,     // source                (1, 1, 1, 1) - (Rd, Gd, Bd, Ad)
       blend_one_minus_src_color,      // destination           (1, 1, 1, 1) - (Rs, Gs, Bs, As)
       blend_src_alpha,                // source or destination (As, As, As, As)
       blend_one_minus_src_alpha,      // source or destination (1, 1, 1, 1) - (As, As, As, As)
       blend_dst_alpha,                // source or destination (Ad, Ad, Ad, Ad)
       blend_one_minus_dest_alpha,     // source or destination (1, 1, 1, 1) - (Ad, Ad, Ad, Ad)
       blend_src_alpha_saturate,       // source                (f, f, f, 1) - f = min(As, 1 - Ad)
       blend_constant_color,           // source or destination (Rc, Gc, Bc, Ac)
       blend_one_minus_constant_color, // source or destination (1, 1, 1, 1) - (Rc, Gc, Bc, Ac)
       blend_constant_alpha,           // source or destination (Ac, Ac, Ac, Ac)
       blend_one_minus_constant_alpha // source or destination (1, 1, 1, 1) - (Ac, Ac, Ac, Ac)
};
 
Blend Func是一个象素运算,
下面是Blend Func的运算公式:
Rb = (Rs x Sr) + (Rd x Dr)
Gb = (Gs x Sg) + (Gd x Dg)
Bb = (Bs x Sb) + (Bd x Db)
Ab = (As x Sa) +(Ad x Da)
 
“x” 表示乘
“+” 表示加
RGBA 表示的是RGB象素颜色再加上Alpha透明通道
小写“s” 表示源 (source)
小写“d” 表示目标 (destination)
小写”c” 应该是常量的意思吧,不过目前不知怎么用。
小写”f” 不知道什么意思,不过唯一使用的地方有等价的式子:min(As, 1 - Ad)
大写字母“S”和“D”是(源和目标的) 混合因子
这里面所有值都为0 … 1
 
Rb Gb Bb Ab 表示最终运算后的象素值。
实例应用:
使用Alpha值
一般我们一个CL_Surface在draw的时候,什么都不设置,就能够使用透明象素。
那么我么什么都不设置就相当于:
set_blend_func (blend_src_alpha, blend_one_minus_src_alpha);
 
blend_src_alpha 为(As, As, As, As)
blend_one_minus_src_alpha 为(1, 1, 1, 1) - (As, As, As, As)
那么我们公式就可以写成
Rb = (Rs x As) + (Rd x (1-As))
Gb = (Gs x As) + (Gd x (1-As))
Bb = (Bs x As) + (Bd x (1-As))
Ab = (As x As) + (Ad x (1-As))
这样,当As为0时
Rb = Rd,Gb = Gd, Bb=Bd, Ab=1 这样透明效果也就实现了。
 
 
ClanLib中的Canvas例子
在Example中的Canvas中的例子中使用一个图象把目标图象中给掏空了。
其中关键代码:
                     // Set the cutter surface to extract instead of replace colours
                     cutter.set_blend_func(blend_zero, blend_one_minus_src_alpha);
                     cutter.draw(CL_Mouse::get_x(), CL_Mouse::get_y(), canvas_ground->get_gc());
 
                     // Set cutter back to normal (for showing the mousecursor)
                     cutter.set_blend_func(blend_src_alpha, blend_one_minus_src_alpha);
其中blend_zero                为 (0, 0, 0, 0)
blend_one_minus_src_alpha  为 (1, 1, 1, 1) - (As, As, As, As)
那么我们用公式就可以写成
Rb = (Rs x 0) +  (Rd x (1-As))
Gb = (Gs x 0) +  (Gd x (1-As))
Bb = (Bs x 0) +  (Bd x (1-As))
Ab = (As x 0) +  (Ad x (1-As))
 
当该As 为 0时,Ab = Ad 。当As 为 1时, Ad = 0。 这样最终就实现了掏空的画面。