设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 3903|回复: 7
打印 上一主题 下一主题

[RMXP发布] [低效率]位图任意四边形变形

[复制链接]

Lv1.梦旅人

梦石
0
星屑
55
在线时间
323 小时
注册时间
2010-8-21
帖子
666
跳转到指定楼层
1
发表于 2011-4-22 20:56:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
首先说明:效率很低!非常低!

这个方法可以把图片拉成任意四边形
格式:
位图对象.(坐标, 取值方式, debug)

"坐标"是个数组,格式是: [右上x,右上y,右下x,右下y,左下x,左下y]
(为什么没有左上?因为为了方便,定为 0,0)

取值方式, 这个版本有三个 -1,0,1
分别为: 平均,四舍五入,"真实"(有问题,建议不用)       默认是0

bebug是在处理完成时,报告处理情况,默认是false

在这,我只想看一下效率到底有多低(与RGE的效率...根本没法比...).....请大家测试一下,以方便优化版出来...格式:
测试代码 :XXXXX
CPU 主频 :XXXX
内存       :XXXX
Bebug   :XXXXXXXX  把bebug设为true,把弹出来的文字写上。比如:

(以学校的坏机器为例.....)

测试代码:(在标题画面修改)
  1.     array = [400,100,600,480,100,400]
  2.     @sprite.bitmap = @sprite.bitmap.quadrilateral(array,1,true)
复制代码
CPU 2.6Ghz(单)
内存   : 480Mb
Debug:   
取值方式 : -1 :  162199 p   22.36秒....
                   0 : 162199 p   7.875秒
                  1 :  162199 p   31.032秒

效率低原因分析:
浮点运算太多....(没办法,求优化方案....这个算法是根据比例用一次方程解出,下次试试高次方程....)
  1. #==============================================================================
  2. # ■ Bitmap
  3. #------------------------------------------------------------------------------
  4. #  位图类 扩展
  5. #===============================================================================

  6. class Bitmap
  7.   #--------------------------------------------------------------------------
  8.   # ● 任意四边变形
  9.   #--------------------------------------------------------------------------
  10.   def quadrilateral(array, int=0, debug=false)
  11.     time_now = Time.now
  12.     xB, yB, xC, yC,xD,yD = array
  13.     xB, yB, xC, yC,xD,yD = xB.to_f, yB.to_f, xC.to_f, yC.to_f,xD.to_f,yD.to_f
  14.     # 为减少计算次数,浪费变量  ======> 我很傻....?
  15.     @yC_B   = yC - yB
  16.     @xC_B   = xC - xB
  17.     begin
  18.       @k_BC = @yC_B / @xC_B
  19.     rescue
  20.       return print "输入坐标BC线段K值无穷大"
  21.     end
  22.     @xM1_up = yB - @k_BC * xB
  23.     @yC_D   = yC - yD
  24.     @xC_D   = xC - xD
  25.     @k_DC   = @yC_D / @xC_D # 不可能DC直线K值无穷大
  26.     @xM2_up = yD - @k_DC * xD
  27.     @k_B    = yB / xB
  28.     @k_d    = xD / yD # 倒数
  29.     # 生成新位图
  30.     @_x_ = [0.0, xB, xC, xD]
  31.     @_y_ = [0.0, yB, yC, yD]
  32.     qua_bitmap = Bitmap.new(@_x_.max- @_x_.min, @_y_.max - @_y_.min)
  33.     t = Time.now
  34.     pixel_num = 0
  35.     # 穷举坐标
  36.     for y in @_y_.min.to_i ... @_y_.max.to_i
  37.       for x in @_x_.min.to_i ... @_x_.max.to_i
  38.         if y < @k_B * x or x < @k_d * y or
  39.           y > @k_DC * (x - xD) + yD or
  40.           x > (1 / @k_BC) * (y - yB) + xB
  41.           next
  42.         end
  43.         begin
  44.           new_x, new_y = mapping_qua(x, y)
  45.           case int
  46.           when -1
  47.             color = [get_pixel(new_x.floor, new_y.floor)]
  48.             color << get_pixel(new_x.ceil , new_y.floor)
  49.             color << get_pixel(new_x.floor, new_y.ceil )
  50.             color << get_pixel(new_x.ceil , new_y.ceil )
  51.             r = color.inject(0.0){|a,i|a+i.red}
  52.             g = color.inject(0.0){|a,i|a+i.green}
  53.             b = color.inject(0.0){|a,i|a+i.blue}
  54.             a = color.inject(0.0){|a,i|a+i.alpha}
  55.             qua_bitmap.set_pixel(x, y, Color.new(r/4, g/4, b/4, a/4))
  56.           when 0
  57.             color = get_pixel(new_x+0.5, new_y+0.5)
  58.             qua_bitmap.set_pixel(x, y, color)
  59.           when 1
  60.             color1 = get_pixel(new_x.floor, new_y.floor)
  61.             color2 = get_pixel(new_x.ceil , new_y.floor)
  62.             color3 = get_pixel(new_x.floor, new_y.ceil )
  63.             color4 = get_pixel(new_x.ceil , new_y.ceil )
  64.             # Red
  65.             r=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.floor)**2))*color1.red
  66.             r+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.floor)**2))*color2.red
  67.             r+=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.ceil)**2))*color3.red
  68.             r+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.ceil )**2))*color4.red
  69.             # Green
  70.             g=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.floor)**2))*color1.green
  71.             g+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.floor)**2))*color2.green
  72.             g+=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.ceil)**2))*color3.green
  73.             g+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.ceil )**2))*color4.green
  74.             # Blue
  75.             b=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.floor)**2))*color1.blue
  76.             b+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.floor)**2))*color2.blue
  77.             b+=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.ceil)**2))*color3.blue
  78.             b+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.ceil )**2))*color4.blue
  79.             # Alpha
  80.             a=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.floor)**2))*color1.alpha
  81.             a+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.floor)**2))*color2.alpha
  82.             a+=(Math.sqrt((new_x-new_x.floor)**2+(new_y-new_y.ceil)**2))*color3.alpha
  83.             a+=(Math.sqrt((new_x-new_x.ceil)**2+(new_y-new_y.ceil )**2))*color4.alpha
  84.             qua_bitmap.set_pixel(x, y, Color.new(r/2, g/2, b/2, a/2))
  85.           end
  86.           pixel_num += 1
  87.         rescue
  88.           next
  89.         end
  90.       end
  91.       # 9秒刷新画面...不给力啊
  92.       if Time.now - t > 9
  93.         Graphics.update ; t = Time.now
  94.       end
  95.     end
  96.     print "共计渲染#{pixel_num}个像素\n共计耗时#{Time.now - time_now}秒"if debug
  97.     qua_bitmap
  98.   end
  99.   private # 下列方法私有化
  100.   #--------------------------------------------------------------------------
  101.   # ● 映射坐标
  102.   #--------------------------------------------------------------------------
  103.   def mapping_qua(x, y)
  104.     # 根据平面直线之间的关系,运用初中知识可以推出公式
  105.     x, y = x.to_f, y.to_f
  106.     if y <= @_y_[2] / @_x_[2] * x
  107.       # 右边部分
  108.       xM = @xM1_up / (y/x - @k_BC)
  109.       x  = x / xM * self.width
  110.       return x, y * xM / self.width
  111.     else
  112.       # 左边部分
  113.       xM = @xM2_up / (y/x - @k_DC)
  114.       y  = x / xM * self.height
  115.       return y * xM / self.height, y
  116.     end
  117.   end
  118. end
复制代码

点评

试试我在VX区发的斜切吧= =但是我那个是基于角度的,还是要转换= =  发表于 2011-4-23 15:58

评分

参与人数 1星屑 +100 收起 理由
fux2 + 100 辛苦了~

查看全部评分

>>猛戳>>MetalSagaR游戏主页<<这里<<
欢迎提供您的意见

Lv1.梦旅人

梦石
0
星屑
50
在线时间
462 小时
注册时间
2007-7-30
帖子
643
2
发表于 2011-4-22 21:01:01 | 只看该作者
可以考虑导出dll 或找高效的算法
PS: set_pixel get_pixel 很慢
RGE这万年大坑 啥时填起来@@

回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
65
在线时间
385 小时
注册时间
2007-7-27
帖子
4106

开拓者

3
发表于 2011-4-23 06:59:08 | 只看该作者
效率一低就几乎没有使用价值了
话说拉一下就几十秒了,有点……太慢了吧
吸吸
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
4
发表于 2011-4-23 09:26:08 | 只看该作者
考虑到如今处理器的 FPU 性能,这里的浮点运算都是其次了,最需要关心的还是循环内部的 set_pixel、get_pixel。这俩的调用前后分别要锁定和解锁内存,只适合常量时间内的调用。像这种软件渲染的图形算法,必须要直接操纵内存,set_pixel、get_pixel 处于抽象层高层了,跟不上实时。

另外,Ruby 抽象层上任何运算效率都天然低一截,时间上紧张的算法没有人会用 Ruby 来写。直到 Ruby 有一个像 JVM 那样强悍的虚拟机之前,最好都直接生成本地代码。

最后就是一些一眼就能看出不够 DRY 的地方,比如 when 1 下面那段,有不少冗余的运算。
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
55
在线时间
323 小时
注册时间
2010-8-21
帖子
666
5
 楼主| 发表于 2011-4-23 15:23:21 | 只看该作者
回复 苏小脉 的帖子

我原来也是以为set/get_pixel是减慢速度的主要原因,不过我试着把 "case" 部分换成next,结果是6.8秒,仅仅快了1秒,也就是说在学校的老机器跑N次浮点运算用了6.8秒,而16万次
set+get用了1秒,所以我说主要原因是"浮点运算",我也认为在配置较高的PC上,估计(用0)会耗时2..3秒,所以我请大家帮忙测试一下,至于"when 1"嘛..脑子不好用,乱写的,不应该开平方根.....哎....个人认为精灵的缩放以及旋转算法是通过某种方法直接写入显存的说.比CPU->内存->XXX->显存 肯定快的说....再查查资料....像我们这些仅仅懂皮毛的人来说....太难了

点评

对了,我在以前试过,20万次get+10万次set在我的电脑上几乎感觉不到延迟,看来是学校的 机器不给力,下周回去试试  发表于 2011-4-23 19:09
>>猛戳>>MetalSagaR游戏主页<<这里<<
欢迎提供您的意见
回复 支持 反对

使用道具 举报

Lv2.观梦者

傻♂逼

梦石
0
星屑
374
在线时间
1606 小时
注册时间
2007-3-13
帖子
6562

烫烫烫开拓者

6
发表于 2011-4-23 15:56:43 | 只看该作者
david50407 发表于 2011-4-22 21:01
可以考虑导出dll 或找高效的算法
PS: set_pixel get_pixel 很慢

笑而不语
哎呀,蛋疼什么的最有爱了
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
110
在线时间
953 小时
注册时间
2007-4-25
帖子
805
7
发表于 2011-4-24 01:35:18 | 只看该作者
回复 沙漠点灰 的帖子
我原来也是以为set/get_pixel是减慢速度的主要原因,不过我试着把 "case" 部分换成next,结果是6.8秒,仅仅快了1秒

要考虑到线性化之后线性运算的时间。这里的运算本来就比较重量级,线性化后复杂度是没变的,只是路由到更高效的 ALU 芯片了,在二十一世纪的处理器下差别只是一个线性级的改变。

这就好比下列代码:
  1. t = Time.now
  2. D.times do
  3.   arr[1] = 1
  4.   35.0/32
  5. end
  6. p Time.now - t

  7. t = Time.now
  8. D.times do
  9.   b.set_pixel(4, 6, c)
  10.   35/32
  11. end
  12. p Time.now - t
复制代码
一测便知,在当前机器架构下,是把 set_pixel 改为一般的随机访问占得比重高,还是把浮点运算转换为定点运算比重高。

个人认为精灵的缩放以及旋转算法是通过某种方法直接写入显存的说

软件渲染都是 CPU 在主内存中操纵缓冲区,然后软件 bit Blit 到显示内存,这中间经过了 BUS,已经损失了效率。当然,这还是比 get_pixel/set_pixel 快——抽象层越多,效率越低。

2D 游戏时代的游戏机一般都有集成的硬件精灵引擎,比较高级的就支持旋转、缩放等运算的硬件加速,这属于硬件渲染,所有工作 GPU 包办了,没 BUS 的事,这无疑是最高效的。

点评

我们学校的机器烂的可以,播放720p的视频卡的要命....  发表于 2011-4-24 15:04
[email protected]:~> repeat 1 fortune
Matz is nice, so we are nice.
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
75
在线时间
13 小时
注册时间
2013-5-11
帖子
6
8
发表于 2013-6-10 23:45:24 | 只看该作者
LZ,我可以求您签名档的刀剑神域的游戏网址吗

点评

卧槽,别挖坟啊,那个是我接的一个小项目,正在做  发表于 2013-6-13 15:46
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-10 15:35

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表