RidgeLines
stacked mountain ridgelines from ridged fractal noise, where each row's opaque panel hides the range behind it; the noise field loops, so the terrain returns to its start every lap (ridgedFbm)
- Run
swift run --package-path Examples Example-Patterns-RidgeLines- Source
- Examples/Patterns/RidgeLines/Sketch.swift
import Ollin
/// Stacked mountain ridgelines from ridged fractal noise. Each row samples
/// `ridgedFbm` along x (the fold that gathers detail on sharp crests instead
/// of rolling hills), lifts a skyline from it, and paints an opaque panel
/// beneath so nearer ranges occlude the ones behind: a whole landscape from
/// one noise call per point, back to front. The rows share a looping field
/// (`loop:`), so the terrain drifts like weather and returns home each lap:
///
/// ```sh
/// swift run Example-Patterns-RidgeLines --export-loop /tmp/ridgelines.gif
/// ```
@main
final class RidgeLines_Example: Sketch {
private let period = 10.0
override var loopDuration: Double? { period }
private let paper = Color(hex: 0xF4EFE6)
private let ink = Color(hex: 0x2A2E3A)
override func draw() {
background(paper)
let rows = 22
let phase = loopProgress(over: period)
for r in 0 ..< rows {
let depth = Double(r) / Double(rows - 1) // 0 far ... 1 near
let baseline = map(depth * depth, 0, 1, height * 0.30, height * 0.96)
let amplitude = map(depth, 0, 1, height * 0.06, height * 0.20)
// The skyline: one ridged sample per step, rows staggered through
// the field's second axis so each range is its own slice.
var skyline: [Vector2] = []
var x = 0.0
while x <= width {
let n = ridgedFbm(x * 0.0032, Double(r) * 0.83, loop: phase, radius: 0.6)
skyline.append(Vector2(x, baseline - n * amplitude))
x += 6
}
skyline.append(Vector2(width, skyline.last!.y))
// An opaque panel under the skyline hides the ranges behind it;
// nearer ranges ink a touch darker, the aerial-perspective cue.
var panel = skyline
panel.append(Vector2(width, height))
panel.append(Vector2(0, height))
fill(Color.mix(paper, ink, 0.04 + depth * 0.10))
noStroke()
drawPolygon(panel)
stroke(ink)
strokeWeight(map(depth, 0, 1, 0.8, 2.4) * scale)
noFill()
drawPolyline(skyline)
}
}
}