diff options
| -rw-r--r-- | src/main/kotlin/trtrfr/TrtrfrProgram.kt | 89 | ||||
| -rw-r--r-- | src/main/resources/shaders/modules/complex.glsl | 46 | ||||
| -rw-r--r-- | src/main/resources/shaders/newton.glsl | 42 | ||||
| -rw-r--r-- | src/main/resources/shaders/trtrfr.glsl | 93 |
4 files changed, 230 insertions, 40 deletions
diff --git a/src/main/kotlin/trtrfr/TrtrfrProgram.kt b/src/main/kotlin/trtrfr/TrtrfrProgram.kt new file mode 100644 index 0000000..7d2f959 --- /dev/null +++ b/src/main/kotlin/trtrfr/TrtrfrProgram.kt @@ -0,0 +1,89 @@ +package trtrfr + +import org.openrndr.application +import org.openrndr.color.* +import org.openrndr.draw.* +import org.openrndr.math.IntVector2 +import org.openrndr.math.Vector2 +import phenax.utils.* + +fun main() = application { + if (captureEnabled) { + val hiRes = System.getenv("PHENAX_HIRES")?.isNotEmpty() ?: false + configure { + width = if (hiRes) 3840 else 1920 + height = if (hiRes) 2160 else 1080 + windowResizable = false + } + } else { + configure { + width = 640 + height = 360 + windowResizable = false + } + } + + oliveProgram { + val cs by liveComputeShader("trtrfr") + val enableAntialiasing = captureEnabled + val shaderLocalSize = IntVector2(8, 8) + + val outputSize = IntVector2(width, height) + val outputBuffer = colorBuffer(outputSize.x, outputSize.y, type = ColorType.UINT8) + + var scale: Double = 1.0 + var offset: Vector2 = Vector2.ZERO + var moving = false + + program.keyboard.keyDown.listen { + if (it.name == "r") { + scale = 1.0 + offset = Vector2.ZERO + } + } + program.mouse.buttonDown.listen { moving = true } + program.mouse.buttonUp.listen { moving = false } + var lastPos = Vector2.ZERO + program.mouse.moved.listen { + val dimens = Vector2(program.width.toDouble(), program.height.toDouble()) + var pos = (Vector2(it.position.x, -it.position.y) - dimens / 2.0).div(dimens) + val del = lastPos - pos + lastPos = pos + if (moving) offset = offset + del * 5.0 / scale + } + + program.mouse.scrolled.listen { scale = scale * (1 + it.rotation.y / 3) } + + extend { + cs.uniform("enable_antialiasing", enableAntialiasing) + cs.uniform("offset", offset) + cs.uniform("scale", scale) + cs.uniform("seconds", seconds) + cs.image("output_image", 0, outputBuffer.imageBinding(0, ImageAccess.WRITE)) + cs.execute( + (outputBuffer.width + shaderLocalSize.x - 1) / shaderLocalSize.x, + (outputBuffer.height + shaderLocalSize.y - 1) / shaderLocalSize.y, + 1 + ) + drawer.image(outputBuffer, 0.0, 0.0, width.toDouble(), height.toDouble()) + + // val shadow = outputBuffer.shadow + // shadow.download() + // for (y in 0 until outputBuffer.height) { + // for (x in 0 until outputBuffer.width) { + // val c = shadow[x, y] + // shadow[x, y] = + // ColorRGBa( + // Math.pow(c.r, (1.0 / 2.2)), + // Math.pow(c.g, (1.0 / 2.2)), + // Math.pow(c.b, (1.0 / 2.2)), + // c.alpha + // ) + // } + // } + // shadow.upload() + // outputBuffer.saveToFile(java.io.File("screenshot/${program.name}.png"), async = false) + // program.application.exit() + } + } +} diff --git a/src/main/resources/shaders/modules/complex.glsl b/src/main/resources/shaders/modules/complex.glsl new file mode 100644 index 0000000..87114ac --- /dev/null +++ b/src/main/resources/shaders/modules/complex.glsl @@ -0,0 +1,46 @@ +float cosh(float val) { + float tmp = exp(val); + float cosH = (tmp + 1.0 / tmp) / 2.0; + return cosH; +} + +float sinh(float val) { + float tmp = exp(val); + float sinH = (tmp - 1.0 / tmp) / 2.0; + return sinH; +} + +vec2 cmul(vec2 a, vec2 b) { + return vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); +} + +vec2 cdiv(vec2 a, vec2 b) { + float denominator = b.x * b.x + b.y * b.y; + if (denominator == 0.) return a; + return cmul(a, vec2(b.x, -b.y)) / denominator; +} + +vec2 csin(vec2 a) { + return vec2(sin(a.x) * cosh(a.y), cos(a.x) * sinh(a.y)); +} + +vec2 ccos(vec2 a) { + return vec2(cos(a.x) * cosh(a.y), -sin(a.x) * sinh(a.y)); +} + +vec2 ctan(vec2 a) { + return cdiv(csin(a), ccos(a)); +} + +vec2 cpow(vec2 z, int n) { + vec2 res = z; + for (int i = 0; i < 20; i++) { + if (i >= n - 1) break; + res = cmul(z, res); + } + return res; +} + +vec2 cexp(vec2 z) { + return exp(z.x) * vec2(cos(z.y), sin(z.y)); +} diff --git a/src/main/resources/shaders/newton.glsl b/src/main/resources/shaders/newton.glsl index e53b153..a0bcc10 100644 --- a/src/main/resources/shaders/newton.glsl +++ b/src/main/resources/shaders/newton.glsl @@ -2,6 +2,7 @@ layout(local_size_x = 1, local_size_y = 1) in; #include <utils> +#include <complex> #define MAX_ITERATIONS 200 @@ -9,45 +10,6 @@ const float antialiasing = 0.28; uniform float seconds = 0; layout(rgba8) uniform writeonly image2D output_image; -float fabs(float a) { - return a > 0. ? a : -a; -} - -float cosh(float val) { - float tmp = exp(val); - float cosH = (tmp + 1.0 / tmp) / 2.0; - return cosH; -} - -float sinh(float val) { - float tmp = exp(val); - float sinH = (tmp - 1.0 / tmp) / 2.0; - return sinH; -} - -vec2 cmul(vec2 a, vec2 b) { - return vec2(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x); -} - -vec2 cdiv(vec2 a, vec2 b) { - float denominator = b.x * b.x + b.y * b.y; - if (denominator == 0.) return a; - return cmul(a, vec2(b.x, -b.y)) / denominator; -} - -vec2 cpow(vec2 z, int n) { - vec2 res = z; - for (int i = 0; i < 20; i++) { - if (i >= n - 1) break; - res = cmul(z, res); - } - return res; -} - -vec2 cexp(vec2 z) { - return exp(z.x) * vec2(cos(z.y), sin(z.y)); -} - vec2 get_step(vec2 z) { vec2 value = cpow(z, 5) + 2.0 * cpow(z, 3) - vec2(1., 0.); vec2 derivative = 5.0 * cpow(z, 4) + 3.0 * cpow(z, 2); @@ -67,7 +29,7 @@ vec3 image(vec2 uv) { z = prevZ - cmul(factor, get_step(prevZ)); iterations++; - if (fabs(z.x - prevZ.x) < 0.001) break; + if (abs(z.x - prevZ.x) < 0.001) break; } float val = float(iterations) * 10.0 / float(MAX_ITERATIONS); diff --git a/src/main/resources/shaders/trtrfr.glsl b/src/main/resources/shaders/trtrfr.glsl new file mode 100644 index 0000000..080aae0 --- /dev/null +++ b/src/main/resources/shaders/trtrfr.glsl @@ -0,0 +1,93 @@ +#version 430 +layout(local_size_x = 8, local_size_y = 8) in; +precision highp float; + +#include <complex> +#include <sdf> +#include <utils> + +uniform float seconds = 0; +layout(rgba8) uniform writeonly image2D output_image; + +uniform float antialiasing = 0.28; +uniform bool enable_antialiasing = false; + +uniform vec2 offset; +uniform float scale; + +const int MAX_ITERATIONS = 1000; +const float INF_GAP = 10000.0; + +vec3 col_blue1 = srgb(0.33, 0.48, 0.60); +vec3 col_pink1 = srgb(0.98, 0.27, 0.47); +vec3 col_pink2 = srgb(0.84, 0.24, 0.33); +vec3 col_yellow1 = srgb(0.90, 0.69, 0.18); +vec3 col_violet1 = srgb(0.26, 0.11, 0.52); +vec3 col_green1 = srgb(0.24, 0.40, 0.33); +vec3 col_wingpat = srgb(0.12, 0.06, 0.03); +vec3 col_mothbody = srgb(0.12, 0.06, 0.03); +vec3 col_bg = vec3(0); + +vec3 image(vec2 uv) { + vec3 color = col_bg; + + vec2 c = (uv - vec2(0, 0.20)) * 6 / scale + offset; + c = vec2(c.y, c.x); + vec2 z = vec2(0); + vec2 last_z; + int iter; + float last_dist; + for (iter = 0; iter <= MAX_ITERATIONS; iter++) { + last_z = z; + z = csin(ccos(z)) - ctan(z) + c; + last_dist = length(z - last_z); + if (last_dist >= INF_GAP) break; + } + float f = float(iter) / float(MAX_ITERATIONS); + + // Pat + vec2 p = (uv - vec2(0, -0.012)) * vec2(23, 72); + float buttpat = sin(-abs(p.x) - 5) * sin(abs(p.y)) - sin((abs(p.x) - 6) * p.y); + color = mix(color, col_wingpat, (smoothstep(-0.5, 1.0, buttpat)) * step(last_dist, 0.0000003)); + color = mix(color, col_mothbody, (1 - step(last_dist, 0.0000016)) * step(last_dist, 0.05)); + + float gap = 0.504; + vec2 eyesp = uv - vec2(gap / 2., 0.093); + eyesp.x -= round(eyesp.x / gap) * gap; + + float eyes = sdf_circle(eyesp, 0.007); + color = mix(color, mix(col_wingpat, col_bg, 0.22), step(abs(eyes) - 0.003, 0)); + + // Floral + color = mix(color, srgb(0.0, 0.13, 0.08), (1 - step(last_dist, 0.1)) * (1 - step(last_dist, INF_GAP))); + color = mix(color, mix(col_pink1, col_violet1, smoothstep(-0.2, 0.5, f)), step(f, 0.9999)); + color = mix(color, col_yellow1, step(f, 0.016)); + color = mix(color, col_violet1, step(f, 0.008)); + color = mix(color, col_pink2, step(f, 0.005)); + color = mix(color, col_green1, step(f, 0.003)); + + return color; +} + +vec3 antialiased_image(vec2 uv) { + vec2 resolution = vec2(imageSize(output_image).xy); + float s = antialiasing / max(resolution.x, resolution.y); + vec3 sum = vec3(0); + int count = 0; + for (int i = -2; i < 2; i++) + for (int j = -2; j < 2; j++, count++) + sum += image(uv + vec2(i, j) * s); + return sum / count; +} + +void main() { + vec2 resolution = vec2(imageSize(output_image).xy); + if (gl_GlobalInvocationID.x >= resolution.x || gl_GlobalInvocationID.y >= resolution.y) return; + + float aspect_ratio = resolution.y / resolution.x; + vec2 uv = (gl_GlobalInvocationID.xy - resolution / 2) * vec2(1.0, aspect_ratio) / resolution; + + vec3 color = enable_antialiasing ? antialiased_image(uv) : image(uv); + + imageStore(output_image, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1)); +} |
