PathTracer
— render the world in one triangle

Lambert


The Next Estimation
FresnelSpecular | Glass

— render the world in one triangle




Nature Of Code 这本书给我印象最深的就是Flocking示例, 当中的算法来源于Craig Reynolds 1986年 。
CodeOfNature很好的实现了该算法, 但是当中存在一些冗余的计算,以及为了清晰阐述Separation | Alignment | Cohesion这三条规则而采用分别遍历计算,对我来说,不够高效之余,还显得不够直观。这里我对该算法进行了简化。
Boid.prototype.steerToVel = function (desired) {
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxAcceleration);
return steer;
}
Boid.prototype.flock = function (boids) {
let sepRad = 25.0, aliRad = 50.0, cohRad = 50.0;
let sepCount = 0, aliCount = 0, cohCount = 0;
let sepAcc = createVector()
let aliAcc = createVector()
let cohAcc = createVector()
for (let i = 0; i < boids.length; i++) {
let diff = p5.Vector.sub(this.position, boids[i].position);
let d = diff.mag();
if (d === 0) continue;
if (d < sepRad) {
sepAcc.add(diff.normalize().div(d));
sepCount++;
}
if (d...
— source code in this page lies here

最近工作中实现了基于KDTree的3D空间划分,用于实时判断Mesh和Ray的相交,我现在依然惊讶于这个算法的优美和高效。
还是先从工作中逃离一会,试试用Clojure实现一下2D-KDtree,然后在quil框架来些与工作无关的东西看看。
先生成3000个点吧:
(def pts
(repeatedly 3000 (vec2 (q/random (q/width))
(q/random (q/height)))))
调用quil的point函数画出来看看
(doall (map (apply q/point %) pts))

好了, 现在我们可以将这些点通过KDTree算法来进行二维分割了:
(defn divide [pts rect depth]
(when (>= (count pts) 1)
(let [top-left (:p rect)
axis ([:x :y] (mod depth 2))
sort-pts (vec (sort-by (axis %) pts))
median (quot (count pts) 2)
translate (g/translate % (m/- top-left))
left (map translate (subvec sort-pts 0 median))
right (map translate (subvec sort-pts (inc median)))
div-rects (divide-rect
rect axis
(get-in sort-pts [median axis]))]
{:pts...
— source code in this page lies here
Generative-Art常常借助概率分布来构建画面的形式与秩序。
其中最常用的有Gaussian、Uniform和PowerLaw分布函数了,Processing中甚至专门提供了randomGaussian这个函数方法来返回符合标准正态分布的随机数。
最近在翻阅一本概率书籍的时候, 当中提到一种简单的算法来生成符合某概率密度函数的连续随机数(假设下图函数是我们想要的概率分布):
💡 注意自定义函数作为概率密度函数不是数学严谨的,概率也只有相对的意义,函数值相对越大越容易被返回。
这篇帖子主要记录了用这种方法来自定义概率分布并“填充”它们,使用Clojure编程语言绑定的Processing框架Quil。
(defn custom-distribution [pdf dimension]
(loop []
(let [ts (repeatedly dimension rand)
v (apply pdf ts)]
(if (< (rand) v)
(flatten [v ts])
(recur)))))
custom-distribution接受两个参数,第一个参数为自定义的概率分布函数F,第二个参数则是该分布函数的维度。上图的函数实际上常被称为Impulse,因为它很像一次脉搏跳动,将它用代码定义出来,然后调用custom-distribution...