Pygame水波纹效果

时间:2011-10-04 12:43:56

标签: python opengl image-processing pygame effect

我已经谷歌搜索了它,但没有现成的脚本 - 而不是对Flash的相同效果。我已经在The Water Effect Explained上检查了算法,并且还测试了Perlin Noise的实现,它可以很好地模拟平面上的波浪结束。我正在寻找基于鼠标悬停/悬停操作在几个Flash Effects上找到的相同实现。这是针对一个交互式楼层库,我很乐意远离Flash,特别是为了避免代码的这种简单的逆向工程 - 是的,我知道它可以只使用一些现成的flash代码,但我只会用它作为最后的手段。

有没有人为Pygame看过这种效果的合适实现(使用OpenGL与否)?

编辑: 任何人都可以使用OpenCV / OpenGL和Pygame提供此效果的合适实现吗?

这里的罪魁祸首是传递一个值列表的(代码)接口,这些值将通过Python从外部解释器(跟踪器 - 而不是TUIO)发送。我已经尝试了几天,但是Pygame无法像C / C ++代码那样快速生成任何东西(用于OpenGL中的着色器),而且我对C / C ++的了解也是空的。所以目标至少要来自Python代码。

一个很好的例子,与Flash效果不同,但仍然很好Water Simulation using Java applet

(赏金显示的答案没有足够的细节,因为这是最接近'OP无法创建他想要的代码,因为他缺乏基本技能,这个答案可能对几个人有用')。

2 个答案:

答案 0 :(得分:9)

完成作业(又称研究)并尝试将问题上发布的Java代码参考直接转换为Python,并且在尝试让Python / Numpy更新基于的像素颜色的大量数组时有非常非常悲伤的体验他们对涟漪效果的涟漪(抱歉,我的第一语言不是英语)的位置,因此解析效果计算的每一遍的几个(x,y)位置和blitting到屏幕上显示的表面上(随后的阵列) ),我得出结论 - 这是由其他评论者支持的 - Pygame只是不会强大到足以实际遍历整个像素数组并将计算结果应用到每个像素屏幕上的最低速率为24 fps(低于平均体验)。

引用Last Light Productions和前Project Geometrian背后的开发人员,Ian Mallet:

  

PyGame对于像素推送并不是那么好。除了GPU之外,什么都没有。

然后搜索结果是Alkahest的搜索结果 - 这些结果将永远不会真正找到 - 并且基于相同的波纹图像的想法,但这次通过使用透明度透过几层Pygame曲面,我在Gamedev上发布了问题Pygame circular cropping/maskschosen answer实际上证实了我已经担心Pygame永远不会男子气概这一事实。

一天后,我回到了我之前关于发展的想法,并遇到了Ogre3D。事实证明(1)Ogre3D和样本是开源的(2)其中一个例子是与移动物体相互作用的三维水模型,与我试图在二维中实现的完全相同,但是以更专业的方式。

由于我在C / C ++方面的知识是零,我决定询问how to customize the Ogre3D water demo是否可以看到从哪里开始查看,其中一个答案指向了Touchscape中提供SDK的软件(参见this answer)。

Ogre3D几乎把它包裹起来。水涟漪效应,OpenGL(它可能optionally基于硬件使用),游戏引擎和Python包装器通过Python-Ogre - 所以我回答了我自己的问题,

  

任何人都可以使用OpenCV / OpenGL和Pygame提供这种效果的合适实现吗?

基本上是

  

是。查看随SDK提供的Ogre3D的水演示 - 并通过Python-Ogre将其插入Python。

答案 1 :(得分:5)

以下使用numpy可能会让你开始。它应该足够快,尽管你甚至可以在python中获得更快的速度(看看这里http://www.scipy.org/PerformancePython如何)。

顺便提一下,所描述的方法有几个缺点:

  1. 你无法控制涟漪的速度 - 要做到这一点,你必须修改涟漪函数中使用的方程式(如果你弄清楚它与波动方程http://en.wikipedia.org/wiki/Wave_equation的关系,那么你就完成了)< / LI>
  2. “池”的“深度”是固定的(可能太浅)。我添加了一个深度参数来放大效果
  3. 文章读取整数像素偏移 - 你会得到一个更好的结果与插值(我猜你可以用opengl做到这一点,但我在那个领域的知识是零)
  4. 代码:

    import numpy
    
    def ripple(w1, w2, damp, n = 1):
        for _ in xrange(n):
            w2 *= -2
            w2[1:-1,1:-1] += w1[0:-2, 1: -1]
            w2[1:-1,1:-1] += w1[2:  , 1: -1]
            w2[1:-1,1:-1] += w1[1:-1, 0: -2]
            w2[1:-1,1:-1] += w1[1:-1, 2:   ]
            w2 *= .5 * (1. - 1./damp)
            w1, w2 = w2, w1
    
    def refract(x, y, w, rindex, depth = 10):
        sx = x[0,1] - x[0,0]
        sy = y[1,0] - y[0,0]
    
        dw_dx = (w[2: ,1:-1] - w[:-2,1:-1]) / sx * .5
        dw_dy = (w[1:-1,2: ] - w[1:-1,:-2]) / sy * .5
    
        xang = numpy.arctan(dw_dx)
        xrefract = numpy.arcsin(sin(xang) / rindex)
        dx = numpy.tan(xrefract) * dw_dx * depth
    
        yang = numpy.arctan(dw_dy)
        yrefract = numpy.arcsin(sin(yang) / rindex)
        dy = numpy.tan(yrefract) * dw_dy * depth
    
        dx *= numpy.sign(dw_dx)
        dy *= numpy.sign(dw_dy)
    
        xmin = x[0,0]
        xmax = x[0,-1]
        x[1:-1,1:-1] += dx
        x[:,:] = numpy.where(x < xmin, xmin, x)
        x[:,:] = numpy.where(x > xmax, xmax, x)
    
        ymin = y[0,0]
        ymax = y[-1,0]
        y[1:-1,1:-1] += dy
        y[:,:] = numpy.where(y < ymin, ymin, y)
        y[:,:] = numpy.where(y > ymax, ymax, y)
    

    x和y应该是来自numpy.meshgrid调用的网格:这是一个示例用法:

        x,y = meshgrid(x,y)
        w = 10 * exp(- (x*x + y*y))
        w1 = w.copy()
        x1,y1 = meshgrid(r_[0:len(x):1.0], r_[0:len(y):1.0])
        ripple(w, w1, 16) # w1 will be modified
        refract(x1, y1, w1, rindex=2, depth=10) # x1 and y1 will be modified
        numpy.around(x1, out=x1) # but you will get better results with interpolate
        numpy.around(y1, out=y1) #