diff options
| author | Akshay Nair <phenax5@gmail.com> | 2026-10-24 12:09:08 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2026-10-24 13:05:25 +0530 |
| commit | e251d719710a951954e2dd9f93544afc601a6600 (patch) | |
| tree | 1140d17fd3e4da4cfba0a33edb1b4f79d15a357b /src/main/kotlin/blood/BloodProgram.kt | |
| parent | bfd7af6c4772c68f001c5c121b62b134bbca04e4 (diff) | |
| download | art-playground-openrndr-e251d719710a951954e2dd9f93544afc601a6600.tar.gz art-playground-openrndr-e251d719710a951954e2dd9f93544afc601a6600.zip | |
Add blood reaction diffusion
Diffstat (limited to '')
| -rw-r--r-- | src/main/kotlin/blood/BloodProgram.kt | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/main/kotlin/blood/BloodProgram.kt b/src/main/kotlin/blood/BloodProgram.kt new file mode 100644 index 0000000..ed70213 --- /dev/null +++ b/src/main/kotlin/blood/BloodProgram.kt @@ -0,0 +1,120 @@ +package blood + +// import org.openrndr.extra.timer.repeat + +import blood.* +import org.openrndr.WindowMultisample +import org.openrndr.application +import org.openrndr.color.* +import org.openrndr.draw.* +import org.openrndr.extra.noise.perlinLinear +import org.openrndr.extra.shadestyles.fills.gradients.gradient +import org.openrndr.math.IntVector2 +import org.openrndr.math.Vector2 +import org.openrndr.shape.Rectangle +import phenax.utils.* + +fun main() = application { + recordDuration(15.seconds()) + + if (captureEnabled) { + configure { + width = 1920 + height = 1080 + windowResizable = false + multisample = WindowMultisample.SampleCount(8) + } + } else { + configure { + width = 640 + height = 360 + windowResizable = false + } + } + + oliveProgram { + val cell_size = 3.0 + val cell_count = IntVector2(width, height) / cell_size.toInt() + val config = getConfig() + + var cells: Cells = Array(cell_count.y) { Array(cell_count.x) { Vector2(1.0, 0.0) } } + config.initializeState(cells) + + val feedRate = config.feedRate + val killRate = config.killRate + val diffusion = config.diffusion + + fun laplaceThyNeighbour(row: Int, col: Int): Vector2 { + var d = Vector2.ZERO + for (i in -1 until 2) { + for (j in -1 until 2) { + val r = row + i + val c = col + j + val weight = if (i == 0 && j == 0) -1.0 else if (i == 0 || j == 0) 0.2 else 0.05 + if (r >= 0 && r < cell_count.y && c >= 0 && c < cell_count.x) d += cells[r][c] * weight + } + } + return d + } + + fun coerceIn(v: Vector2, min: Double, max: Double): Vector2 { + return Vector2(v.x.coerceIn(min, max), v.y.coerceIn(min, max)) + } + + fun nextState(dt: Double): Cells { + return Array(cell_count.y) { row -> + Array(cell_count.x) { col -> + val d = cells[row][col] + val lapl = laplaceThyNeighbour(row, col) + val u = -d.x * d.y * d.y + feedRate * (1 - d.x) + val v = d.x * d.y * d.y - (feedRate + killRate) * d.y + var change = lapl * diffusion + Vector2(u, v) + coerceIn(d + change * dt, 0.0, 1.0) + } + } + } + + val col_flesh = ColorRGBa(0.53, 0.20, 0.20) + val col_blood = ColorRGBa(0.34, 0.00, 0.00) + + fun drawCell(pos: Vector2, amounts: Vector2) { + var color = col_flesh.opacify(0.0) + + run { + val noiseScale = 0.99 + val noise = perlinLinear(100, pos.x * noiseScale, pos.y * noiseScale) + color = mix(color, col_flesh.shade(1.1).opacify(0.14), noise) + } + + color = mix(color, col_blood, (amounts.y * 3).coerceIn(0.0, 1.0)) + if (amounts.y > 0.38) color = mix(color, ColorRGBa.BLACK, amounts.y * 0.08) + if (amounts.y > 0.40) color = mix(color, ColorRGBa.WHITE, amounts.y * 0.28) + + drawer.fill = color + drawer.stroke = drawer.fill + drawer.rectangle(pos.x * cell_size, pos.y * cell_size, cell_size, cell_size) + } + + extend { repeat(config.iterationsPerFrame) { cells = nextState(0.8) } } + + extend { + drawer.clear(col_flesh) + drawer.shadeStyle = + gradient<ColorRGBa> { + stops[0.4] = col_flesh + stops[0.9] = col_flesh.shade(0.65) + radial {} + } + drawer.rectangle( + Rectangle.fromCenter(drawer.bounds.center, width.toDouble(), height.toDouble()) + ) + drawer.shadeStyle = null + drawer.strokeWeight = 0.0 + for ((row, rowdiff) in cells.withIndex()) { + for ((col, diff) in rowdiff.withIndex()) { + drawCell(Vector2(col.toDouble(), row.toDouble()), diff) + } + } + } + } +} |
