工作坊讲义:Processing 入门
本次工作坊是创意编程课程的第一部分,面向没有编程经验的同学,目标是用 Processing 完成一组方格图像,并理解生成艺术中最基础的方法:规则加随机。工作坊分两次进行,第一次讲程序结构、坐标和随机函数,第二次完成练习并导出图片。请提前在 processing.org 下载并安装 Processing。
先介绍 Processing 的来历。2001 年,凯西·瑞斯(Casey Reas)和本·弗莱(Ben Fry)发起了这个项目,两人都来自 MIT 媒体实验室的美学与计算小组,这个小组由约翰·前田(John Maeda)在 1996 年创立。项目的目标是让不以编程为业的人,在视觉的语境里学会编程的基本概念。最早的网站在 2001 年 10 月上线,名字写作 Proce55ing。
Processing 部分借鉴了前田 1999 年发布的 Design By Numbers。那是一个为设计师准备的极简编程环境,只能画灰度图,画布只有 100 × 100 像素;Processing 保留了“为视觉创作者编程”的出发点,又突破了这些限制。它基于 Java 语言,以开源方式发展。2005 年,瑞斯和弗莱因 Processing 获得 Ars Electronica 的金尼卡奖(Net Vision 类别)。
2012 年,两人与丹尼尔·希夫曼(Daniel Shiffman)一起成立了 Processing 基金会。2013 年,劳伦·麦卡锡(Lauren McCarthy)发起 p5.js,用 JavaScript 重新实现 Processing 的思路,让草图可以直接在浏览器里运行,也可以用一个链接分享给别人。本次工作坊用桌面版 Processing,课后有兴趣的同学可以把作业移植到 p5.js 上。
Processing 把一个程序叫作“草图”(sketch),保存草图的文件夹叫“草图本”(sketchbook)。这个说法有意强调探索:写代码不必先设计好再一次写完,而可以像画速写一样边写边看、边改边试。课上请保持这个习惯,每改一处就运行一次,观察画面怎样变化。
一个最简单的草图由两个函数组成。setup() 在程序启动时运行一次,用来设置画布大小、背景色等;draw() 在 setup() 之后反复执行,默认每秒 60 帧,直到程序停止或调用 noLoop()。做动画时,变化写在 draw() 里;只画一张静态图时,可以在 draw() 末尾调用 noLoop(),让它只执行一次。
Processing 的坐标系和数学课上的不同:原点 (0, 0) 在画布左上角,x 向右增大,y 向下增大。用 size(600, 600) 建一张 600 × 600 像素的画布后,右下角那个像素的坐标是 (599, 599)。画方格之前,先在纸上画出坐标草图,标出第一个格子和最后一个格子的位置,可以少走很多弯路。
本次只用到几个基本函数:background() 设置背景色,stroke() 和 fill() 设置线条与填充颜色,noFill() 取消填充,rect() 画矩形,quad() 画任意四边形。rect() 默认前两个参数是左上角的坐标,后两个是宽和高。这些函数在 processing.org 的参考文档里都能查到,每个页面都附有可运行的小例子。
random() 是生成艺术里最常用的函数。random(10) 返回 0 到 10 之间的一个随机小数,不包括 10;random(-5, 5) 返回 -5 到 5 之间的数。每次运行结果都不同;如果想反复得到同一张图,可以在开头调用 randomSeed() 并传入一个固定的数,这样 random() 每次都会给出同一串数。
noise() 返回的是 Ken Perlin 在 1980 年代提出的 Perlin 噪声。它的值总在 0 到 1 之间,和 random() 的区别是:相邻的输入会得到相近的输出,变化连续而平滑。参考文档建议相邻两次取值的输入只差 0.005 到 0.03。用 random() 得到的是“跳动”,用 noise() 得到的是“起伏”,两者适合不同的画面。
练习参照维拉·莫尔纳的方格作品。莫尔纳 1968 年起用计算机创作,她的《中断》(Interruptions,1968–1969)从排成方阵的短线开始,随机旋转每一条线,再随机抹去一些区域;1974 年的《(Des)Ordres》用嵌套的正方形组成阵列,再用参数打乱它们的规整。我们的练习只取其中最简单的一步:先建立规则,再加入有控制的随机扰动。
第一步,建立规则。画布设为 600 × 600,背景白色,只画线不填充。用两层循环画出 10 行 10 列的正方形阵列,每格边长 40 像素,格与格之间留出间隔,整体居中。核心只有一行:rect(x, y, s, s); 其中 x、y 由行号和列号算出,s 是边长。运行后应该得到一张完全规整的方格图,这是后面所有变化的基准。
第二步,加入随机扰动。把 rect() 换成 quad(),四个角各自在原位置上加一个 random(-d, d) 的偏移。先让所有格子的 d 都一样,观察画面;再让 d 随行号增大,第一行几乎不动,最后一行明显变形。画面由此有了从秩序到无序的渐变,这是体会“随机的分寸”最直接的办法。
第三步,比较 random() 和 noise()。把偏移量改成由 noise() 计算,输入用格子的行号和列号乘以一个小系数,再把 0 到 1 的结果换算到 -d 到 d 之间。和 random() 的版本并排比较:前者每个格子各抖各的,后者相邻格子的变形连成一片,像被同一股力量推过。记下你更喜欢哪一种,以及为什么。
第四步,自选一项变化:在每个格子里画三到五层嵌套的正方形,每层单独扰动;或者以一定概率跳过某些格子,留出空白,就像《中断》里被抹去的区域;或者只扰动一种颜色的线条。无论选哪一项,都要把规则写成一句话,比如“越靠右下,嵌套层数越少,扰动越大”。
导出图片。静态图可以在 draw() 末尾调用 saveFrame("grid-####.png"),#### 会被替换成帧编号,避免覆盖之前的文件;也可以写在 keyPressed() 里,按键时才保存。saveFrame() 支持 TIFF、TARGA、JPEG 和 PNG 格式,交作业请用 PNG,导出后检查图片尺寸是否为 600 × 600。
作业要求:提交三张不同参数的 PNG 图片、完整的草图文件夹,以及一段 200 字左右的说明。说明里要写清三件事:你的规则是什么,随机作用在哪里、范围多大,三张图之间改变了哪个参数。截止时间为下次课前一天,文件按“学号-姓名-方格”命名。
最后留一个问题。完成作业后你会发现,写规则花的时间并不多,大部分时间花在调参数和挑图上。这正是创意编程的日常:程序负责执行,人负责设定规则、判断结果、决定保留哪一张。生成艺术里“艺术家设计的是过程”这句话,在这里会有更具体的体会。下次课请带着自己的三张图来讨论。
这是一份课程资料,仅对校内师生开放。