SDL 实现Alpha混合 (Normal Mode)

作者:V君 发布于:2013-8-21 17:43 Wednesday 分类:挖坑经验

要想拥有一个绚丽的界面, 透明混合是少不了的.

这几天的酱油中, V君每天都在使用SDL做各种尝试.

一个界面框架的雏形正在诞生...

点击查看原图

别看这张截图已经实现透明混合 实际上这里是每一帧都进行重绘,

各种元素都是打散Blit, 坐标都是相对于屏幕 不但复杂还性能缓慢,

对话框只要开出两三个就会导致帧数急剧下降.

因此, 需要将每个元素/容器的图像预先渲染到一个Surface, 

每一帧只需要blit到帧缓冲区就行了, 还能使用相对坐标.

但V君在做这个预渲染的时候遇到了不少麻烦.

起初整个容器和子元素都半透明(不贴图啦).

调整一些属性之后绘制的子元素总算正常, 但文本渲染还是跟着半透明了.

点击查看原图

继续尝试/咕狗/总结...

得出结论:

SDL将两个带有Alpha通道的Surface的其中一个Blit到另一个时得到的结果竟然是这样的.

截图中的绿色半透明和红色梯形色块是容器Surface,文字Blit到上面.

然后将容器Blit到帧缓冲区, 结果就得到这幅鸟样,这是什么模式啊魂淡!!!

于是这两天就集中精力去弄懂这个问题.

...过程略... (各种代码尝试,咕狗,甚至发帖到StackOverflow)

不断地换关键字,找到这里 

http://stackoverflow.com/questions/7438263/alpha-compositing-algorithm-blend-modes 

起初直接将代码复制过来不加以修改, 结果直接出现除零错误...

然后开始啃这个帖子提到的 SVG alpha compositing spec 进去稍微开始啃算法说明

看了一会之后回来这个帖子尝试理解代码, 基于上面的代码做修改和调试

该说是说功夫不负有心人呢还是瞎猫撞上死耗子? 233 

总算是被 V君 歪打正着的尝试出来.

点击查看原图点击查看原图

贴一段主体代码~

-


//全部数据类型是float 源rgba值除以255

alpha_final = alpha_bg + alpha_fg - alpha_bg * alpha_fg;

 

red_fg_a = red_fg * alpha_fg;

green_fg_a = green_fg * alpha_fg;

blue_fg_a = blue_fg * alpha_fg;

 

red_bg_a = red_bg * alpha_bg;

green_bg_a = green_bg * alpha_bg;

blue_bg_a = blue_bg * alpha_bg;

 

red_final_a = red_fg_a + red_bg_a * (1 - alpha_fg);

green_final_a = green_fg_a + green_bg_a * (1 - alpha_fg);

blue_final_a = blue_fg_a + blue_bg_a * (1 - alpha_fg);

 

red_final = red_final_a.Dd(alpha_final);

green_final = green_final_a.Dd(alpha_final);

blue_final = blue_final_a.Dd(alpha_final);

 

alpha_final = alpha_bg + alpha_fg - alpha_bg * alpha_fg; 

 

//最后使用计算出来的值放到目标Surface

//rgba(red_final, green_final, blue_final, alpha_final)

-

其中 Dd扩展方法是用啦避免除零错误

遇到除数为零直接返回0,  这样或许不够严谨, 但最跑出的结果似乎正确 233.

 

已经是下班时间啦, 收工回去喽. 

假如明天还是没有任务, 那就继续完善吧. 233

标签: 软件开发 C# SDL

引用地址:

发表评论:

Powered by emlog 去你妹的备案 sitemap