Escher 风格的拟周期密铺

周末刚完成了一个有点烧脑的 Shadertoy 项目,Escher 风格的拟周期密铺

你可以修改变量 N 的值,以及数组 shifts 来获得不同的图案。其中当 N=4 时得到的是 Ammann-Beenker 密铺,N=5 以及 shifts 的值均为 0.2 时给出的是经典的 Penrose 密铺。

你能看出这个动画的奥妙之处在哪里吗?

直观上看,这个动画由一些错落有致,但又无缝拼接在一起的房间组成,每个房间有三个面可见,这三个面上各自绘制了一些“窗户”,房间的颜色、窗户的开闭、朝向都是不断变化的,但是仔细一看,诶,好像一些房间的窗口的朝向是“矛盾”的哎?这种整体布局和谐但是局部细节与真实世界矛盾的艺术风格由埃舍尔 (1898-1972) 所创立,所以这个作品也可以叫做 Escher 风格的不可能密铺。

实际上在这个动画里面基本的几何元素只有菱形,这些菱形分为两种:胖菱形和瘦菱形。在代码中我是对每一个像素,首先确定其所属的菱形,然后计算它到各个装饰元素 (菱形边界、窗户、窗台) 的 signed distance field 函数 \(d\),根据 \(d\) 的值来混合颜色,特别还根据菱形的类型和方向加上了阴影的效果,使得整个画面看起来有立体感。

生成动画中菱形排列的算法非常奇妙,它来自 de Bruijn 1981 年的发现,是所谓构造拟周期密铺的网格法 1 (aperiodic tiling),而添加窗户的点缀则是受到了 Greg Egan 的 Javascript 动画启发。我很久之前就知道 de Bruijn 的方法,但是看到 Greg Egan 的动画以后还是萌发了在 shader 里面做出一个更漂亮的 3D 效果来的想法。这个念头憋了好久,终于前几天利用晚上业余时间动手折腾了一番,捣鼓出了上面的效果,当然只是一个伪 3D 的效果。我的动画与 Greg Egan 不同的地方在于 Greg Egan 是精心选择了每一个菱形的窗户的开口方向,使得所有的房间的窗户看起来都是矛盾的;而我这里为了让窗户也能动起来只是随机选择了其开口的方向,所以只有部分房间的窗户是矛盾的。

代码中窗户的绘制方法参考了 Greg Egan 的代码和注释,特别致谢。


  1. N.G. de Bruijn. Algebraic theory of Penrose's non-periodic tilings of the plane.↩︎

 | 

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器