createCanvas(600, 600, WEBGL)
fbo = createFramebuffer()
depthShader = createShader(vert, frag)
for (const corner of [0, 1, 2, 3]) {
const r = cellSize*sqrt(2)/2
[cos((corner+0.5)*PI/2)*r, 0, sin((corner+0.5)*PI/2)*r],
[cos((corner+1.5)*PI/2)*r, 0, sin((corner+1.5)*PI/2)*r],
const [a, b, c] = verts.map((v) => createVector(...v))
const n = a.copy().sub(b).cross(c.copy().sub(b)).normalize()
for (const vert of verts) {
for (const zSide of [-1, 1]) {
[-cellSize/2, 0, zSide * cellSize/2],
[cellSize/2, 0, zSide * cellSize/2],
[cellSize/2, cellSize, zSide * cellSize/2],
const [a, b, c] = verts.map((v) => createVector(...v))
const n = a.copy().sub(b).cross(c.copy().sub(b)).normalize().mult(-zSide)
for (const vert of verts) {
for (let i = 0; i < corners.length; i++) {
for (const off of [0,1]) {
const [x,y] = corners[(i+off)%corners.length]
for (const zSide of [-1, 1]) {
verts.push([x, y, zSide * cellSize/2])
const [a, b, c] = verts.map((v) => createVector(...v))
const n = a.copy().sub(b).cross(c.copy().sub(b)).normalize()
beginShape(TRIANGLE_STRIP)
for (const vert of verts) {
ortho(-width / 2, width / 2, height / 2, -height / 2, 0, far)
translate(-cellSize * numCells / 2, -height * 0.2, -cellSize * numCells / 2)
for (let x = 0; x < numCells; x++) {
for (let z = 0; z < numCells; z++) {
translate((x+0.5)*cellSize, 0, (z+0.5)*cellSize)
const h = floor(pow(random(0, 1),3)*5 + 1)*cellSize
rotateY(random([0, 1, 2, 3]) * TWO_PI/4)
depthShader.setUniform('uImg', fbo.color)
depthShader.setUniform('uDepth', fbo.depth)
depthShader.setUniform('uSize', [width, height])
rect(0, 0, width, height)
function mousePressed() {
saveCanvas('modern_vampires_of_the_city.png')