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

Project1

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

[胡扯] 论用RGSS画复变函数图像

[复制链接]

Lv3.寻梦者

梦石
0
星屑
1934
在线时间
403 小时
注册时间
2015-8-30
帖子
395
跳转到指定楼层
1
发表于 2018-9-9 20:03:53 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 有丘直方 于 2018-9-9 20:40 编辑

这个东西貌似已经有人搞过了??
RUBY 代码复制
  1. # Color
  2. class Color
  3.  
  4.   # 根据HSL数据来生成颜色对象,第四个参数是不透明度
  5.   def self.hsl(hue, saturation, lightness, alpha = 1.0)
  6.     saturation = saturation.clamp(0.0, 1.0)
  7.     lightness = lightness.clamp(0.0, 1.0)
  8.     alpha = alpha.clamp(0.0, 1.0)
  9.  
  10.     times = (hue * 3 / Math::PI).modulo(6)
  11.     amount1 = (1 - (2 * lightness - 1).abs) * saturation
  12.     amount2 = amount1 * (1 - (times % 2 - 1).abs)
  13.     correction = lightness - amount1 / 2
  14.     translation = (times.to_i + 1) % 6
  15.  
  16.     args = [0, 0, 0]
  17.     args[translation / 2] = amount1
  18.     args[2 - translation % 3] = amount2
  19.  
  20.     new(*args.map {|origin| (origin + correction) * 255 }, alpha * 255)
  21.   end
  22.  
  23.   # 在此颜色之上按正常方式叠加另一个颜色时呈现的颜色
  24.   def blend(other)
  25.     alpha1 = alpha / 255.0
  26.     alpha2 = other.alpha / 255.0
  27.     calc_blend = proc do |c1, c2|
  28.       c1 /= 255.0
  29.       c2 /= 255.0
  30.       blend = c1 * alpha1 * (1 - alpha2) + c2 * alpha2
  31.       blend /= alpha1 + alpha2 - alpha1 * alpha2
  32.       blend *= 255
  33.     end
  34.     result = Color.new
  35.     result.alpha = (alpha1 + alpha2 - alpha1 * alpha2) * 255
  36.     result.red = calc_blend.call(red, other.red)
  37.     result.green = calc_blend.call(green, other.green)
  38.     result.blue = calc_blend.call(blue, other.blue)
  39.     result
  40.   end
  41.  
  42.   # blend的破坏型方法
  43.   def blend!(other)
  44.     set(blend(other))
  45.     self
  46.   end
  47.  
  48. end
  49.  
  50. # Comparable
  51. module Comparable
  52.  
  53.   # 返回在min和max的范围内最接近self的对象
  54.   def clamp(min, max)
  55.     return min if self <=> min < 0
  56.     return max if self <=> max > 0
  57.     self
  58.   end
  59.  
  60. end
  61.  
  62. # 关于x的以mean为期望,variance为方差的正态分布函数
  63. # 不给出mean和variance参数时是标准正态分布函数
  64. def Math.normal_distribution(x, mean = 0.0, variance = 1.0)
  65.   exp(-(x - mean) ** 2 / (2 * variance)) / sqrt(2 * self::PI * variance)
  66. end
  67.  
  68. # Complex
  69. class Complex
  70.  
  71.   # 获取此复数对应的定义域着色
  72.   # lightness_base: 用于计算亮度的函数中的底数,越小越亮,必须在0和1之间
  73.   # saturation: 饱和度
  74.   def to_color(lightness_base = 0.5, saturation = 1.0)
  75.     raise unless lightness_base.between?(0, 1)
  76.     exponent = abs
  77.     hue = exponent == 0 ? 0.0 : arg
  78.     lightness = 1 - lightness_base ** exponent
  79.     Color.hsl(hue, saturation, lightness)
  80.   end
  81.  
  82.   # 获取此复数对应的结构化的定义域着色
  83.   # 这种着色方案有特殊效果,具体看参数说明
  84.   # discontinuity_base: 当此复数的模是达到参数的整数次幂时,亮度骤然变为最低
  85.   # saturation: 饱和度
  86.   # min_lightness: 不考虑网格和射线时能达到的最低亮度
  87.   # lightness_range: 不考虑网格和射线时能达到的最高和最低亮度之差
  88.   # grid_hue: 网格的色相
  89.   # rays_hue: 射线的色相
  90.   # grid_lightness: 网格的亮度
  91.   # rays_lightness: 射线的亮度
  92.   # grid_density: 网格线的密度,复数的实部或虚部是参数的倒数的整数倍时出现网格
  93.   # rays_density: 射线的密度,复数的俯角是参数的倒数的整数倍时出现射线
  94.   # grid_radius: 网格线的宽度的一半,不包括扩散出去的部分
  95.   # rays_radius: 射线的宽度的一半,不包括扩散出去的部分
  96.   # grid_restraint: 网格线的扩散度,越大越模糊
  97.   # rays_restraint: 射线的扩散度,越大越模糊
  98.   # grid_opacity: 网格的不透明度,如果不想显示网格请设为0.0
  99.   # rays_opacity: 射线的不透明度,如果不想显示射线请设为0.0
  100.   def to_color_structured(discontinuity_base = 2.0, saturation = 1.0,
  101.       min_lightness = 0.3, lightness_range = 0.4, grid_hue = 0.0,
  102.       rays_hue = 0.0, grid_lightness = 0.0, rays_lightness = 1.0,
  103.       grid_density = 1.0, rays_density = 6.0, grid_radius = 0.005,
  104.       rays_radius = 0.01, grid_restraint = 60.0, rays_restraint = 50.0,
  105.       grid_opacity = 0.2, rays_opacity = 0.8)
  106.     antilog = abs
  107.     hue = antilog == 0 ? 0.0 : arg
  108.  
  109.     lightness_phase = Math.log(antilog, discontinuity_base).modulo(1)
  110.     lightness_phase = 0.0 if lightness_phase.nan?
  111.     lightness = lightness_phase * lightness_range + min_lightness
  112.  
  113.     color = Color.hsl(hue, saturation, lightness)
  114.     f = Math.sqrt(2 * Math::PI)
  115.  
  116.     dense_real = real * grid_density
  117.     real_distance = (dense_real - dense_real.round).abs
  118.     dense_imaginary = imaginary * grid_density
  119.     imaginary_distance = (dense_imaginary - dense_imaginary.round).abs
  120.     grid_distance = [[real_distance, imaginary_distance].min, grid_radius].max
  121.     grid_excursion = (grid_distance - grid_radius) * grid_restraint
  122.     grid_alpha = Math.normal_distribution(grid_excursion) * f * grid_opacity
  123.     grid_color = Color.hsl(grid_hue, saturation, grid_lightness, grid_alpha)
  124.     color.blend!(grid_color)
  125.  
  126.     rays_distances = Array.new(rays_density) do |i|
  127.       slope = Math.tan(i / rays_density * Math::PI)
  128.       (slope * real - imaginary).abs / Math.hypot(slope, -1)
  129.     end
  130.     rays_distance = [rays_distances.min, rays_radius].max
  131.     rays_excursion = (rays_distance - rays_radius) * rays_restraint
  132.     rays_alpha = Math.normal_distribution(rays_excursion) * f * rays_opacity
  133.     rays_color = Color.hsl(rays_hue, saturation, rays_lightness, rays_alpha)
  134.     color.blend!(rays_color)
  135.   end
  136. end
  137.  
  138. # Bitmap
  139. class Bitmap
  140.   # 绘制复变函数的函数图像
  141.   # function: 需要绘制的函数,提供接受一个复数参数并返回复数的call方法
  142.   # delta_x: 图中1像素的距离代表的大小
  143.   # structured: 是否采用结构化的图像,见Complex#to_color_structured
  144.   # ox: 自变量取0+0i时所在的位置的相对于位图的x坐标
  145.   # oy: 自变量取0+0i时所在的位置的相对于位图的y坐标
  146.   def draw_function(function, delta_x, structured = false,
  147.     ox = Graphics.width / 2, oy = Graphics.height / 2)
  148.     width.times do |x|
  149.       height.times do |y|
  150.         real = (x - ox) * delta_x
  151.         imaginary = (oy - y) * delta_x
  152.         complex = function.call(Complex(real, imaginary))
  153.         color = structured ? complex.to_color_structured : complex.to_color
  154.         set_pixel(x, y, color)
  155.       end
  156.     end
  157.   end
  158. end
一个简单的用于玩耍的代码(依赖这玩意)(由于我用了RGD所以无视分辨率限制了)(虽然不用多线程能画得更快,但是那样就看不到图像慢慢绘制出来的过程了):
RUBY 代码复制
  1. # 玩耍方法:在控制台输入你想要画的函数,然后等待即可
  2. Graphics.resize_screen(1024, 768)
  3. sprite = Sprite.new
  4. sprite.bitmap = Bitmap.new(Graphics.width, Graphics.height)
  5. Thread.start do
  6.   loop do
  7.     print("f(z) = ")
  8.     string = $stdin.gets
  9.     function = eval("->(z) { #{string} }")
  10.     puts("Please wait...")
  11.     time = Time.now
  12.     sprite.bitmap.draw_function(function, 0.008, true) rescue puts($!.message)
  13.     printf("Completed after %d seconds.\n", Time.now - time)
  14.   end
  15. end
  16.  
  17. rgss_stop
配上CMath后玩耍体验更佳:
RUBY 代码复制
  1. #==============================================================================
  2. # * CMath
  3. #------------------------------------------------------------------------------
  4. # Trigonometric and transcendental functions for complex numbers.
  5. # CMath is a library that provides trigonometric and transcendental functions
  6. # for complex numbers. The functions in this module accept integers, floating-
  7. # point numbers or complex numbers as arguments.
  8. # Note that the selection of functions is similar, but not identical, to that
  9. # in module math. The reason for having two modules is that some users aren't
  10. # interested in complex numbers, and perhaps don't even know what they are. They
  11. # would rather have Math.sqrt(-1) raise an exception than return a complex
  12. # number.
  13. # For more information you can see Complex class.
  14. #==============================================================================
  15.  
  16. module CMath
  17.  
  18.   include Math
  19.  
  20.   alias exp! exp
  21.   alias log! log
  22.   alias log2! log2
  23.   alias log10! log10
  24.   alias sqrt! sqrt
  25.   alias cbrt! cbrt
  26.  
  27.   alias sin! sin
  28.   alias cos! cos
  29.   alias tan! tan
  30.  
  31.   alias sinh! sinh
  32.   alias cosh! cosh
  33.   alias tanh! tanh
  34.  
  35.   alias asin! asin
  36.   alias acos! acos
  37.   alias atan! atan
  38.   alias atan2! atan2
  39.  
  40.   alias asinh! asinh
  41.   alias acosh! acosh
  42.   alias atanh! atanh
  43.  
  44.   #--------------------------------------------------------------------------
  45.   # * exp(z)
  46.   #--------------------------------------------------------------------------
  47.   # Math::E raised to the z power
  48.   #--------------------------------------------------------------------------
  49.   def exp(z)
  50.     if z.real?
  51.       exp!(z)
  52.     else
  53.       ere = exp!(z.real)
  54.       Complex(ere * cos!(z.imag),
  55.               ere * sin!(z.imag))
  56.     end
  57.   end
  58.  
  59.   #--------------------------------------------------------------------------
  60.   # * log(z, b=::Math::E)
  61.   #--------------------------------------------------------------------------
  62.   # Returns the natural logarithm of Complex. If a second argument is given,
  63.   # it will be the base of logarithm.
  64.   #--------------------------------------------------------------------------
  65.   def log(*args)
  66.     z, b = args
  67.     if z.real? and z >= 0 and (b.nil? or b >= 0)
  68.       log!(*args)
  69.     else
  70.       a = Complex(log!(z.abs), z.arg)
  71.       if b
  72.         a /= log(b)
  73.       end
  74.       a
  75.     end
  76.   end
  77.  
  78.   #--------------------------------------------------------------------------
  79.   # * log2(z)
  80.   #--------------------------------------------------------------------------
  81.   # Returns the base 2 logarithm of z
  82.   #--------------------------------------------------------------------------
  83.   def log2(z)
  84.     if z.real? and z >= 0
  85.       log2!(z)
  86.     else
  87.       log(z) / log!(2)
  88.     end
  89.   end
  90.  
  91.   #--------------------------------------------------------------------------
  92.   # * log10(z)
  93.   #--------------------------------------------------------------------------
  94.   # Returns the base 10 logarithm of z
  95.   #--------------------------------------------------------------------------
  96.   def log10(z)
  97.     if z.real? and z >= 0
  98.       log10!(z)
  99.     else
  100.       log(z) / log!(10)
  101.     end
  102.   end
  103.  
  104.   #--------------------------------------------------------------------------
  105.   # * sqrt(z)
  106.   #--------------------------------------------------------------------------
  107.   # Returns the non-negative square root of Complex.
  108.   #--------------------------------------------------------------------------
  109.   def sqrt(z)
  110.     if z.real?
  111.       if z < 0
  112.         Complex(0, sqrt!(-z))
  113.       else
  114.         sqrt!(z)
  115.       end
  116.     else
  117.       if z.imag < 0 ||
  118.         (z.imag == 0 && z.imag.to_s[0] == '-')
  119.         sqrt(z.conjugate).conjugate
  120.       else
  121.         r = z.abs
  122.         x = z.real
  123.         Complex(sqrt!((r + x) / 2), sqrt!((r - x) / 2))
  124.       end
  125.     end
  126.   end
  127.  
  128.   #--------------------------------------------------------------------------
  129.   # * cbrt(z)
  130.   #--------------------------------------------------------------------------
  131.   # Returns the principal value of the cube root of z
  132.   #--------------------------------------------------------------------------
  133.   def cbrt(z)
  134.     if z.real?
  135.       cbrt!(z)
  136.     else
  137.       Complex(z) ** (1.0/3)
  138.     end
  139.   end
  140.  
  141.   #--------------------------------------------------------------------------
  142.   # * sin(z)
  143.   #--------------------------------------------------------------------------
  144.   # Returns the sine of z, where z is given in radians
  145.   #--------------------------------------------------------------------------
  146.   def sin(z)
  147.     if z.real?
  148.       sin!(z)
  149.     else
  150.       Complex(sin!(z.real) * cosh!(z.imag),
  151.               cos!(z.real) * sinh!(z.imag))
  152.     end
  153.   end
  154.  
  155.   #--------------------------------------------------------------------------
  156.   # * cos(z)
  157.   #--------------------------------------------------------------------------
  158.   # Returns the cosine of z, where z is given in radians
  159.   #--------------------------------------------------------------------------
  160.   def cos(z)
  161.     if z.real?
  162.       cos!(z)
  163.     else
  164.       Complex(cos!(z.real) * cosh!(z.imag),
  165.               -sin!(z.real) * sinh!(z.imag))
  166.     end
  167.   end
  168.  
  169.   #--------------------------------------------------------------------------
  170.   # * tan(z)
  171.   #--------------------------------------------------------------------------
  172.   # Returns the tangent of z, where z is given in radians
  173.   #--------------------------------------------------------------------------
  174.   def tan(z)
  175.     if z.real?
  176.       tan!(z)
  177.     else
  178.       sin(z) / cos(z)
  179.     end
  180.   end
  181.  
  182.   #--------------------------------------------------------------------------
  183.   # * sinh(z)
  184.   #--------------------------------------------------------------------------
  185.   # Returns the hyperbolic sine of z, where z is given in radians
  186.   #--------------------------------------------------------------------------
  187.   def sinh(z)
  188.     if z.real?
  189.       sinh!(z)
  190.     else
  191.       Complex(sinh!(z.real) * cos!(z.imag),
  192.               cosh!(z.real) * sin!(z.imag))
  193.     end
  194.   end
  195.  
  196.   #--------------------------------------------------------------------------
  197.   # * cos(z)
  198.   #--------------------------------------------------------------------------
  199.   # Returns the hyperbolic cosine of z, where z is given in radians
  200.   #--------------------------------------------------------------------------
  201.   def cosh(z)
  202.     if z.real?
  203.       cosh!(z)
  204.     else
  205.       Complex(cosh!(z.real) * cos!(z.imag),
  206.               sinh!(z.real) * sin!(z.imag))
  207.     end
  208.   end
  209.  
  210.   #--------------------------------------------------------------------------
  211.   # * tanh(z)
  212.   #--------------------------------------------------------------------------
  213.   # Returns the hyperbolic tangent of z, where z is given in radians
  214.   #--------------------------------------------------------------------------
  215.   def tanh(z)
  216.     if z.real?
  217.       tanh!(z)
  218.     else
  219.       sinh(z) / cosh(z)
  220.     end
  221.   end
  222.  
  223.   #--------------------------------------------------------------------------
  224.   # * asin(z)
  225.   #--------------------------------------------------------------------------
  226.   # Returns the arc sine of z
  227.   #--------------------------------------------------------------------------
  228.   def asin(z)
  229.     if z.real? and z >= -1 and z <= 1
  230.       asin!(z)
  231.     else
  232.       (-1.0).i * log(1.0.i * z + sqrt(1.0 - z * z))
  233.     end
  234.   end
  235.  
  236.   #--------------------------------------------------------------------------
  237.   # * acos(z)
  238.   #--------------------------------------------------------------------------
  239.   # Returns the arc cosine of z
  240.   #--------------------------------------------------------------------------
  241.   def acos(z)
  242.     if z.real? and z >= -1 and z <= 1
  243.       acos!(z)
  244.     else
  245.       (-1.0).i * log(z + 1.0.i * sqrt(1.0 - z * z))
  246.     end
  247.   end
  248.  
  249.   #--------------------------------------------------------------------------
  250.   # * atan(z)
  251.   #--------------------------------------------------------------------------
  252.   # Returns the arc tangent of z
  253.   #--------------------------------------------------------------------------
  254.   def atan(z)
  255.     if z.real?
  256.       atan!(z)
  257.     else
  258.       1.0.i * log((1.0.i + z) / (1.0.i - z)) / 2.0
  259.     end
  260.   end
  261.  
  262.   #--------------------------------------------------------------------------
  263.   # * atan2(z)
  264.   #--------------------------------------------------------------------------
  265.   # returns the arc tangent of y divided by x using the signs of y and x to
  266.   # determine the quadrant
  267.   #--------------------------------------------------------------------------
  268.   def atan2(y,x)
  269.     if y.real? and x.real?
  270.       atan2!(y,x)
  271.     else
  272.       (-1.0).i * log((x + 1.0.i * y) / sqrt(x * x + y * y))
  273.     end
  274.   end
  275.  
  276.   #--------------------------------------------------------------------------
  277.   # * asinh(z)
  278.   #--------------------------------------------------------------------------
  279.   # returns the inverse hyperbolic sine of z
  280.   #--------------------------------------------------------------------------
  281.   def asinh(z)
  282.     if z.real?
  283.       asinh!(z)
  284.     else
  285.       log(z + sqrt(1.0 + z * z))
  286.     end
  287.   end
  288.  
  289.   #--------------------------------------------------------------------------
  290.   # * acosh(z)
  291.   #--------------------------------------------------------------------------
  292.   # returns the inverse hyperbolic cosine of z
  293.   #--------------------------------------------------------------------------
  294.   def acosh(z)
  295.     if z.real? and z >= 1
  296.       acosh!(z)
  297.     else
  298.       log(z + sqrt(z * z - 1.0))
  299.     end
  300.   end
  301.  
  302.   #--------------------------------------------------------------------------
  303.   # * atanh(z)
  304.   #--------------------------------------------------------------------------
  305.   # returns the inverse hyperbolic tangent of z
  306.   #--------------------------------------------------------------------------
  307.   def atanh(z)
  308.     if z.real? and z >= -1 and z <= 1
  309.       atanh!(z)
  310.     else
  311.       log((1.0 + z) / (1.0 - z)) / 2.0
  312.     end
  313.   end
  314.  
  315.   module_function :exp!
  316.   module_function :exp
  317.   module_function :log!
  318.   module_function :log
  319.   module_function :log2!
  320.   module_function :log2
  321.   module_function :log10!
  322.   module_function :log10
  323.   module_function :sqrt!
  324.   module_function :sqrt
  325.   module_function :cbrt!
  326.   module_function :cbrt
  327.  
  328.   module_function :sin!
  329.   module_function :sin
  330.   module_function :cos!
  331.   module_function :cos
  332.   module_function :tan!
  333.   module_function :tan
  334.  
  335.   module_function :sinh!
  336.   module_function :sinh
  337.   module_function :cosh!
  338.   module_function :cosh
  339.   module_function :tanh!
  340.   module_function :tanh
  341.  
  342.   module_function :asin!
  343.   module_function :asin
  344.   module_function :acos!
  345.   module_function :acos
  346.   module_function :atan!
  347.   module_function :atan
  348.   module_function :atan2!
  349.   module_function :atan2
  350.  
  351.   module_function :asinh!
  352.   module_function :asinh
  353.   module_function :acosh!
  354.   module_function :acosh
  355.   module_function :atanh!
  356.   module_function :atanh
  357.  
  358.   module_function :frexp
  359.   module_function :ldexp
  360.   module_function :hypot
  361.   module_function :erf
  362.   module_function :erfc
  363.   module_function :gamma
  364.   module_function :lgamma
  365.  
  366. end


顺便一提,虽然绘制速度慢到让人吐血,但是由于不支持后台运行,请将焦点保持在窗口上,慢慢看着它画完;我也不是很清楚为什么RGD不支持这个
再顺便一提,要是RGD有更高的Ruby版本就好了,我就不用写Complex(1, 2),直接写1+2i了

评分

参与人数 1+1 收起 理由
David_Exmachina + 1

查看全部评分

小仙女一枚~

Lv3.寻梦者

可以吃的头衔

梦石
0
星屑
1000
在线时间
423 小时
注册时间
2010-10-17
帖子
602
2
发表于 2018-9-10 03:43:57 | 只看该作者
尝试用Shader完成这个效果把(效率会让你惊呆

点评

主要耗时不在绘制,而是计算。1024*768次循环的复杂的没有经过优化的计算,能不慢吗  发表于 2018-9-10 19:13
……
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-4-20 09:07

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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