diff options
| author | Akshay Nair <phenax5@gmail.com> | 2026-09-20 15:53:10 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2026-09-20 15:53:10 +0530 |
| commit | 7bdd84e8ecade87ececdefe3cee614df8438e0a1 (patch) | |
| tree | 5228218d87c08ca348a549d3444c12657439a694 /src | |
| parent | 70e53263b259c6b73a03ec16fe819bfce5f1ecb7 (diff) | |
| download | art-playground-openrndr-7bdd84e8ecade87ececdefe3cee614df8438e0a1.tar.gz art-playground-openrndr-7bdd84e8ecade87ececdefe3cee614df8438e0a1.zip | |
Wood pattern flow field(wip)
Diffstat (limited to '')
| -rw-r--r-- | src/main/kotlin/phenax/utils/program.kt | 22 | ||||
| -rw-r--r-- | src/main/kotlin/wood/WoodProgram.kt | 83 | ||||
| -rw-r--r-- | src/main/resources/shaders/warping.glsl | 4 | ||||
| -rw-r--r-- | src/main/resources/shaders/wood.glsl | 60 |
4 files changed, 165 insertions, 4 deletions
diff --git a/src/main/kotlin/phenax/utils/program.kt b/src/main/kotlin/phenax/utils/program.kt index ced3e3a..fe48351 100644 --- a/src/main/kotlin/phenax/utils/program.kt +++ b/src/main/kotlin/phenax/utils/program.kt @@ -5,6 +5,7 @@ import kotlin.properties.ReadOnlyProperty import org.openrndr.ApplicationBuilder import org.openrndr.Program import org.openrndr.draw.* +import org.openrndr.color.* import org.openrndr.extra.filewatcher.watchingFile import org.openrndr.extra.olive.oliveProgram as oliveProgramOriginal @@ -57,6 +58,27 @@ fun preprocessShader(shaderCode: String): String { val defaultShaderCode: String = "" +fun averageColor(cb: ColorBuffer): ColorRGBa { + val shadow = cb.shadow + shadow.download() + + var r = 0.0 + var g = 0.0 + var b = 0.0 + var a = 0.0 + for (y in 0 until cb.height) { + for (x in 0 until cb.width) { + val c = shadow[x, y] + r += c.r + g += c.g + b += c.b + a += c.alpha + } + } + val n = (cb.width * cb.height).toDouble() + return ColorRGBa(r / n, g / n, b / n, a / n) +} + fun Program.liveComputeShader(name: String): ReadOnlyProperty<Any?, ComputeShader> { val shaderCode by watchingFile(File("src/main/resources/shaders/${name}.glsl")) { file -> diff --git a/src/main/kotlin/wood/WoodProgram.kt b/src/main/kotlin/wood/WoodProgram.kt new file mode 100644 index 0000000..66ae071 --- /dev/null +++ b/src/main/kotlin/wood/WoodProgram.kt @@ -0,0 +1,83 @@ +package wood + +import org.openrndr.application +import org.openrndr.color.* +import org.openrndr.draw.* +import org.openrndr.extra.noise.filters.SimplexNoise3D +import org.openrndr.math.IntVector2 +import org.openrndr.math.Vector2 +import org.openrndr.math.Vector3 +import org.openrndr.shape.IntRectangle +import phenax.utils.* + +fun main() = application { + recordDuration(5.seconds()) + + configure { + width = 640 + height = 480 + windowResizable = false + } + + oliveProgram { + val cs by liveComputeShader("wood") + + val outputBuffer = colorBuffer(width, height, type = ColorType.UINT8) + + val size = Math.max(width, height) * 2 + val noiseBuffer = colorBuffer(size, size, type = ColorType.UINT8) + val noiseFilter = SimplexNoise3D() + noiseFilter.scale = Vector3.ONE * 1.8 + noiseFilter.octaves = 8 + noiseFilter.premultipliedAlpha = false + noiseFilter.seed = Vector3(0.1, 2.6, 0.1) + noiseFilter.apply(emptyArray(), noiseBuffer) + + var flowField: MutableList<Double> = mutableListOf() + val subdiv = IntVector2(20, 20) + var subBuffer = colorBuffer(size / subdiv.x, size / subdiv.y) + for (row in 1..subdiv.y) { + for (col in 1..subdiv.x) { + val pos = IntVector2((col - 1) * subBuffer.width, (row - 1) * subBuffer.height) + noiseBuffer.copyTo( + subBuffer, + sourceRectangle = IntRectangle(pos, subBuffer.width, subBuffer.height), + targetRectangle = IntRectangle(0, 0, subBuffer.width, subBuffer.height) + ) + flowField.add(averageColor(subBuffer).r) + } + } + + var particles: MutableList<Vector2> = mutableListOf() + val particles_count = 5 + for (i in 0..(particles_count - 1)) { + particles.add(Vector2(0.5, 0.5)) + } + var particle_velocities = particles.map { Vector2(0.001, 0.0) }.toMutableList() + println(particles) + println(particles_count) + + extend { + for ((index, particle) in particles.withIndex()) { + val gpos = Vector2(particle.x * subdiv.x, particle.y * subdiv.y) + val fidx = gpos.x.toInt() + gpos.y.toInt() * subdiv.y + if (flowField.count() > fidx && fidx >= 0) { + val current_cell = flowField[fidx] + particle_velocities[index] += Vector2(0.0, current_cell/1000000.0) + } + particles[index] += particle_velocities[index] + } + } + + extend { + cs.uniform("particles", particles.toTypedArray()) + cs.uniform("particles_count", particles_count) + cs.uniform("flow_field", flowField.toTypedArray()) + cs.image("noise_texture", 1, noiseBuffer.imageBinding(0, ImageAccess.READ)) + cs.uniform("seconds", seconds) + cs.image("output_image", 0, outputBuffer.imageBinding(0, ImageAccess.WRITE)) + cs.execute(outputBuffer.width, outputBuffer.height, 1) + drawer.image(outputBuffer) + } + } +} diff --git a/src/main/resources/shaders/warping.glsl b/src/main/resources/shaders/warping.glsl index 044e324..a607007 100644 --- a/src/main/resources/shaders/warping.glsl +++ b/src/main/resources/shaders/warping.glsl @@ -1,10 +1,6 @@ #version 430 layout(local_size_x = 1, local_size_y = 1) in; -#include <sdf> -#include <utils> -#include <noise> - uniform float seconds = 0; layout(rgba8) uniform readonly image2D noise_texture; layout(rgba8) uniform writeonly image2D output_image; diff --git a/src/main/resources/shaders/wood.glsl b/src/main/resources/shaders/wood.glsl new file mode 100644 index 0000000..5dec360 --- /dev/null +++ b/src/main/resources/shaders/wood.glsl @@ -0,0 +1,60 @@ +#version 430 +layout(local_size_x = 1, local_size_y = 1) in; + +uniform float seconds = 0; +layout(rgba8) uniform readonly image2D noise_texture; +layout(rgba8) uniform readonly image2D subtexture; +layout(rgba8) uniform writeonly image2D output_image; + +uniform float flow_field[400]; +uniform vec2 particles[100]; +uniform int particles_count; + +float sample_noise(in vec2 p) { + vec4 noise = imageLoad(noise_texture, ivec2(p * imageSize(noise_texture))); + return noise.x; +} + +float gen_pattern(in vec2 p, out vec3 coloring_factor, out vec3 coloring_factor2) { + float s1 = sample_noise(p + sample_noise(p) * vec2(0.5, 0.1)); + float s2 = sample_noise(p + sample_noise(p) * vec2(0.8, 0.4)); + float s3 = sample_noise(p + sample_noise(p)); + coloring_factor = vec3(0.204, 0.11, 0.01) * vec3(s1 * s2, 0.3 * s3, 0.3 * s3); + coloring_factor2 = vec3(0.4, 0.3 * s3, 0.3 * s3); + return sample_noise(p + s2 * s1 * s3); +} + +vec3 srgb(in float r, in float g, in float b) { + return vec3(pow(r, 2.2), pow(g, 2.2), pow(b, 2.2)); +} + +void main() { + vec2 uv = vec2(gl_GlobalInvocationID.xy) / imageSize(output_image).xy; + + // vec3 coloring_factor; + // vec3 coloring_factor2; + // float v = gen_pattern(uv, coloring_factor, coloring_factor2); + // coloring_factor = srgb(0.941, 0.827, 0.706); + // coloring_factor2 = srgb(0.204, 0.11, 0.01); + // coloring_factor2 = srgb(0.204, 0.11, 0.01); + // coloring_factor2 = srgb(0.104, 0.06, 0.00); + // vec3 color = mix(coloring_factor, coloring_factor2, clamp(v, 0., 1.)); + + ivec2 grid = ivec2(20, 20); + vec2 p = uv * grid; + int ffidx = int(p.x) + int(p.y) * grid.y; + float cell = flow_field[ffidx]; + // vec3 color = vec3(ffidx/400.); + vec3 color = vec3(cell); + // subtexture + + for (int i = 0; i < particles_count; i++) { + vec2 p = particles[i]; + if (length(uv - p) - 0.01 <= 0) { + color = vec3(1, 0, 0); + } + } + + // color = imageLoad(noise_texture, ivec2(uv * imageSize(output_image).xy)).xyz; + imageStore(output_image, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1)); +} |
