首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
 您现在的位置: 中国IT实验室 >> 游戏开发 >> 游戏开发入门 >> 正文
64K色模式下的快速Alpha混合算法
来源:ChinaItLab 作者: 时间:2004-12-8


  在32/64K色模式下,由于每个点的RGB值是放在一个字里,以16位色为例,一般是按RGB或BGR 565存放。传统的软件Alpha混合算法是先将RGB分离出来,分开运算,然后再合成。这造成了16位模式下的alpha混合比24位模式下慢 的现象,但使用16位色真的那么慢吗?我认为如果不使用MMX指令,15/16的比24位的快。因为我们可以使用一个小的技巧来同时计算RGB。而24位颜色,除非使用MMX指令,否则必须分开计算R、G、B。
  先设颜色(color)是RGB 565的,那么按二进制看,这个颜色字是这样分布的:
  
  RRRRR GGGGGG BBBBB
  5位  6位   5位
  
  RGB成分
  
  而386以上CPU都有32位的寄存器,我们只需要将16位RGB变形为:
  
  00000 GGGGGG 00000 RRRRR 000000 BBBBB
  5位  6位    5位  5位   6位  5位
  
  变形后的RGB成分
  
  储存在32位寄存器中,(就是把绿色提到前16位里)由于64K色下颜色深度是32级的,所以alpha也只用分32级就能满足需要。那么对上面变形过的双字处理,可以同时算RGB了。(Color1*Alpha+Color2*(32-Alpha))/32能不能简化为(Color1-Color2)*Alpha/32+Color2?我思考过这个问题,以为减法将产生负数,这样再算乘法时有可能出问题,但是经过测试,这样简化似乎又没有问题。毕竟极小的误差是可以忽略的。
  
  最近温习了一下汇编,今天用NASM写了个C可调用的Alpha混合函数(32位模式,我针对DJGPP写的)并进行了Pentium优化(针对双流水线,有错请指出)。大家看看,有BUG,还能优化或有更快的方法也请一定告诉我。顺便提一下,上面提到的化简没有体现到下面的程序中,而且,使用乘法本身是个错误。只是看看吧,如果你想实际运用,请参考Allegro程序库的做法。
  
  ; 对16位的color1与color2进行Alpha混合
  ; R=(r1*alpha+r2*(32-alpha))/32
  ; G=(g1*alpha+g2*(32-alpha))/32
  ; B=(b1*alpha+b2*(32-alpha))/32
  
  ; C 语言调用函数(32 位保护模式)Pentium双流水线优化
  ; By Cloud Wu (cloudwu@263.net)
  ;       (http://member.netease.com/~cloudwu)
  ; -------------------------------------------------------------------------
  ; unsigned long alpha (unsigned long c1,unsigned long c2,unsigned long alpha);
  ; -------------------------------------------------------------------------
  ; c1: 颜色1的RGB(565),c2: 颜色2的RGB(565),alpha: Alpha值(0~31)
  ; NASM 编译通过
  
  [BITS 32]
  [GLOBAL _alpha]
  [SECTION .text]
  
  _alpha:
  
  ; 初始化代码
  push ebp      ; ebp 压栈
  mov ebp,esp    ; 保存 esp 到 ebp
  mov edi,0x7e0f81f ; dx=00000111111000001111100000011111
  add esp,8     ; esp 指向参数 c1
  pop eax      ; 弹出 c1 到 ax
  pop ebx      ; 弹出 c2 到 bx
  
  ; 处理颜色
  mov cx,ax     ; cx=r1..b1
  mov dx,bx     ; dx=r2..b2
  sal eax,16     ; eax=r1g1b1......
  sal ebx,16     ; ebx=r2g2b2......
  mov ax,cx     ; eax=r1g1b1r1g1b1
  mov bx,dx     ; ebx=r2g2b2r2g2b2
  and eax,edi    ; eax=..g1..r1..b1
  pop esi      ; 弹出 alpha
  mul esi      ; eax*=alpha
  neg esi      ; -alpha
  and ebx,edi    ; ebx=..g2..r2..b2
  add esi,0x20    ; 32-alpha
  xchg eax,ebx    ; 交换 eax,ebx
  mul esi      ; c2*=(32-alpha)
  add eax,ebx    ; c1*alpha+c2*(32-alpha)
  mov esp,ebp
  sar eax,5     ; color=(c1*alpha+c2*(32-alpha))/32
  
  ;还原成 RGB 形式
  pop ebp
  and eax,edi    ; color=..g..r..b
  mov cx,ax     ;
  sar eax,16     ;
  or ax,cx      ; color=rgb (eax)
  ret
  
  如果建一张256K的表来查表预处理RGB怎样?经过尝试,发现速度不仅没有提高,反而降低了。分析的结论是,256K的表太大了,以至于不能放到缓存(Cache)里,反而没有计算的方法快,毕竟计算的话,每行的代码都很快,而不必和内存打交道。真正加速的方法是什么?借鉴Allegro程序库里的方法,建立32个函数分别计算每个alpha值的情况。这样,alpha值变成固定的,从而可以使用LEA、ADD、SUB、SAL、SAR来替代缓慢的MUL。经过实践,我重写了Allegro程序库里的cblend15.c及cblend16.c,(使用程序库自己的Test.exe,机器配置为Cyrix Gx/120 S3/375 4M)测试数据如下:
  
  原有的混合函数 使用新算法的混合函数 将Blender函数置为空
  1402 per sec 1779 per sec 2002 per sec
  
  呵呵,速度提高了一倍不是吗?Allegro库目前的版本已经使用了我写的blender函数。
  
【责编:admin】

中国IT教育热线咨询

相关文章
游戏开发新手入门之位图化图形
给希望成为游戏美术设计师的朋友
Ogre游戏引擎鼠标选取物体演示  
所有绘画的核心灵魂——素描知识
DirectDraw与DirectInput游戏编程体验
推荐文章

 精彩友情推荐
·Asp源码 PHP源码
·CGI源码 JSP源码
·建站书籍教程
·服务器软件 .net源码
·建站工具软件
·IDC资讯大全
·机房品质万里行
·IDC托管必备知识
·全国IDC报价
·网站推广优化
 基础入门  开发文档
 最新推荐
  多数的Windows程序都需要Windows.h和Windowsx.h这两个头文件,要确保使用它们。当然,你还需要其它......
游戏引擎演化史
在Windows上安装OGRE的方法
关于滤镜遮罩概念,Sobel 遮罩
游戏开发新手入门之Windows编程
游戏开发新手入门之位图化图形
教你实现卡通渲染的另类勾边方法
游戏设计大师谈如何成为一名游戏设
Visual C#编写 3D游戏框架示例
真正的 Java 学习从入门到精通
游戏开发经验——游戏开发的基本常
  为什么要研究攻击行为在人类有记载的5600年的历史中,共计发生了14,400次战争;今天,平均一天要发生............
游戏开发中显示对话的特殊句法
游戏原型设计的介绍
网络游戏中的攻击行为
谈动作类游戏的必要条件
规则的多元分析模式
载入位图文件到DirectDraw
Archer Game Suite 是什么?
浅谈游戏企划-新手入门篇
暴雪称霸游戏业界的六大秘密绝招
骨骼动画及示例Skinned Mesh的解析
  培训中心