aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-10-01 15:00:35 +0530
committerAkshay Nair <phenax5@gmail.com>2026-10-01 15:00:35 +0530
commitb04c4008e73d1515d1f78f993ca25826847d7207 (patch)
treee884360817b047eae4db05e36595a0c7f40a1399 /src
parent0fc4f3de01b6ef63e1fc8d36d581a542b3c27a42 (diff)
downloadart-playground-openrndr-b04c4008e73d1515d1f78f993ca25826847d7207.tar.gz
art-playground-openrndr-b04c4008e73d1515d1f78f993ca25826847d7207.zip
Add time
Diffstat (limited to '')
-rw-r--r--src/main/kotlin/mrdoor/MrdoorProgram.kt8
-rw-r--r--src/main/kotlin/time/TimeProgram.kt78
-rw-r--r--src/main/resources/shaders/mrdoor.glsl67
-rw-r--r--src/main/resources/shaders/time.glsl147
4 files changed, 271 insertions, 29 deletions
diff --git a/src/main/kotlin/mrdoor/MrdoorProgram.kt b/src/main/kotlin/mrdoor/MrdoorProgram.kt
index deabfe3..5d60505 100644
--- a/src/main/kotlin/mrdoor/MrdoorProgram.kt
+++ b/src/main/kotlin/mrdoor/MrdoorProgram.kt
@@ -19,15 +19,15 @@ fun main() = application {
oliveProgram {
val cs by liveComputeShader("mrdoor")
- val cameraManager =
- CameraManager(Vector3(1.0, 1.0, -1.0), Vector3.ZERO, Vector3(20.0, 30.0, -30.0))
- extend(cameraManager)
+ // val cameraManager =
+ // CameraManager(Vector3(1.0, 1.0, -1.0), Vector3.ZERO, Vector3(20.0, 30.0, -30.0))
+ // extend(cameraManager)
val outputBuffer = colorBuffer(width, height, type = ColorType.UINT8)
extend {
cs.uniform("seconds", seconds)
- cameraManager.setUniforms(cs)
+ // cameraManager.setUniforms(cs)
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/kotlin/time/TimeProgram.kt b/src/main/kotlin/time/TimeProgram.kt
new file mode 100644
index 0000000..d62b1ac
--- /dev/null
+++ b/src/main/kotlin/time/TimeProgram.kt
@@ -0,0 +1,78 @@
+package time
+
+import java.time.LocalTime
+import org.openrndr.application
+import org.openrndr.color.*
+import org.openrndr.draw.*
+import org.openrndr.extra.noise.filters.SimplexNoise3D
+import org.openrndr.math.*
+import phenax.utils.*
+
+fun main() = application {
+ recordDuration(5.seconds())
+
+ if (recordingEnabled || screenshotEnabled) {
+ configure {
+ width = 1920
+ height = 1080
+ windowResizable = false
+ }
+ } else {
+ configure {
+ width = 640
+ height = 360
+ windowResizable = false
+ }
+ }
+
+ oliveProgram {
+ val char_size = 200.0
+ val font = program.loadFont("data/fonts/default.otf", char_size)
+ val cs by liveComputeShader("time")
+
+ val outputBuffer = colorBuffer(width, height, type = ColorType.UINT8)
+
+ val size = Math.max(width, height) * 4
+ val noiseBuffer = colorBuffer(size, size, type = ColorType.UINT8)
+ val noiseFilter = SimplexNoise3D()
+ noiseFilter.scale = Vector3.ONE * 2.4
+ noiseFilter.octaves = 8
+ noiseFilter.premultipliedAlpha = true
+ noiseFilter.seed = Vector3(0.01, 0.01, 0.001)
+ noiseFilter.apply(emptyArray(), noiseBuffer)
+
+ val characters = 0..9
+ val textTarget =
+ renderTarget(char_size.toInt() * characters.count(), char_size.toInt()) {
+ colorBuffer(type = ColorType.UINT8)
+ }
+
+ extend {
+ cs.image("noise_texture", 1, noiseBuffer.imageBinding(0, ImageAccess.READ))
+
+ drawer.isolatedWithTarget(textTarget) {
+ drawer.clear(ColorRGBa.TRANSPARENT)
+ drawer.ortho(textTarget)
+ drawer.fontMap = font
+ drawer.fill = ColorRGBa.WHITE
+ for (char in characters) {
+ drawer.text(char.toString(), Vector2(char * char_size.toDouble(), char_size / 2.0 + 5))
+ }
+ }
+
+ val textBuffer = textTarget.colorBuffer(0)
+
+ cs.image("text_texture", 2, textBuffer.imageBinding(0, ImageAccess.READ))
+
+ val time = LocalTime.now()
+ cs.uniform("hours", time.getHour().toFloat())
+ cs.uniform("minutes", time.getMinute().toFloat())
+ cs.uniform("seconds", time.getSecond().toFloat())
+
+ cs.uniform("time", 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/mrdoor.glsl b/src/main/resources/shaders/mrdoor.glsl
index a37cbab..19290ce 100644
--- a/src/main/resources/shaders/mrdoor.glsl
+++ b/src/main/resources/shaders/mrdoor.glsl
@@ -6,13 +6,14 @@ layout(local_size_x = 1, local_size_y = 1) in;
#include <noise>
uniform float seconds = 0;
-uniform vec3 camera_position = vec3(0, 1, 0);
-uniform mat3 camera_transformation;
-uniform vec3 key_light_position;
+uniform vec3 camera_position = vec3(0, 1.7, -2);
+uniform vec3 key_light_position = vec3(0.8, 3, 0.4);
layout(rgba8) uniform writeonly image2D output_image;
-const vec3 door1_light_position = vec3(0.8, 4, 0.4);
-const vec3 sunlight_color = vec3(1, 0.99, 0.99);
+uniform float antialiasing = 0.28;
+
+// const vec3 door1_light_position = vec3(0.8, 4, 0.4);
+// const vec3 sunlight_color = vec3(1, 0.99, 0.99);
#define PI 3.14159265358979323
@@ -47,7 +48,7 @@ Obj scene(in vec3 p) {
float door1angle;
timing_actions(door1angle);
vec3 hingepos = vec3(-1.0, 0, -0.0);
- debugshapesdist = min(debugshapesdist, sdf_circle(doorpos - hingepos, 0.1));
+ // debugshapesdist = min(debugshapesdist, sdf_circle(doorpos - hingepos, 0.1));
doorpos = vec3(
hingepos.x + (doorpos.x - hingepos.x) * cos(door1angle) - (doorpos.z - hingepos.z) * sin(door1angle),
doorpos.y,
@@ -61,7 +62,7 @@ Obj scene(in vec3 p) {
doorhandle.shine = 22.0;
Obj door = create_obj(2, doorbody);
door.material = vec3(0.68, 0.17, 0.20);
- door.shine = 2.0;
+ door.shine = 0.2;
float doorframe = ssubtract(
sdf_box(roompos - vec3(0, 0.5, 0), vec3(2., 2.6, 0.1), 0),
@@ -75,7 +76,7 @@ Obj scene(in vec3 p) {
Obj walls = create_obj(2, min(min(doorframe, wallsides), roof));
walls.material = vec3(0.15, 0.28, 0.42);
- debugshapesdist = min(debugshapesdist, sdf_circle(p - door1_light_position, 0.1));
+ // debugshapesdist = min(debugshapesdist, sdf_circle(p - door1_light_position, 0.1));
Obj debug = create_obj(-1, debugshapesdist);
debug.lighting = false;
debug.material = vec3(0, 1, 0);
@@ -145,13 +146,9 @@ float shadow_scene(in vec3 ray_origin, in vec3 ray_direction, in float light_int
return res * res * (3.0 - 2.0 * res);
}
-void main() {
- vec2 resolution = vec2(imageSize(output_image).xy);
- float aspect_ratio = resolution.y / resolution.x;
- vec2 uv = (gl_GlobalInvocationID.xy - resolution / 2) * vec2(1.0, aspect_ratio) / resolution;
-
+vec3 image(vec2 uv) {
vec3 origin = vec3(0);
- vec3 uv_direction = normalize((vec3(uv.x, uv.y, 1) - origin) * camera_transformation + origin);
+ vec3 uv_direction = normalize(vec3(uv.x, uv.y, 1));
Obj obj = ray_march_scene(camera_position, uv_direction);
vec3 p = camera_position + uv_direction * obj.dist;
@@ -168,23 +165,43 @@ void main() {
// key_contrast *= shadow_scene(p, keyl_dir, 8.);
key_contrast = clamp(key_contrast, 0, 1);
- vec3 door1_ldir = normalize(door1_light_position - p);
- float door1_contrast = 1.;
- door1_contrast *= clamp(dot(normal, door1_ldir), 0, 1);
- door1_contrast *= shadow_scene(p, door1_ldir, 128.);
- door1_contrast = clamp(door1_contrast, 0, 1);
+ // vec3 door1_ldir = normalize(door1_light_position - p);
+ // float door1_contrast = 1.;
+ // door1_contrast *= clamp(dot(normal, door1_ldir), 0, 1);
+ // // door1_contrast *= shadow_scene(p, door1_ldir, 128.);
+ // door1_contrast = clamp(door1_contrast, 0, 1);
- float contrast = max(key_contrast, door1_contrast);
+ float contrast = key_contrast; // max(key_contrast, door1_contrast);
color *= clamp(ambient + contrast * (1.0 - ambient), 0, 1);
- vec3 hal_door1 = normalize(door1_ldir - uv_direction);
- float spec_door1 =
- pow(clamp(dot(normal, hal_door1), 0.0, 1.0), 16.0) * contrast *
+ vec3 hal = normalize(keyl_dir - uv_direction);
+ float spec =
+ pow(clamp(dot(normal, hal), 0.0, 1.0), 16.0) * contrast *
(0.04 +
- 0.96 * pow(clamp(1.0 + dot(hal_door1, uv_direction), 0.0, 1.0), 5.0));
- color += obj.shine * spec_door1 * vec3(1.00, 0.70, 0.5);
+ 0.96 * pow(clamp(1.0 + dot(hal, uv_direction), 0.0, 1.0), 5.0));
+ color += obj.shine * spec * vec3(1.00, 0.70, 0.5);
}
+ 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);
+ float aspect_ratio = resolution.y / resolution.x;
+ vec2 uv = (gl_GlobalInvocationID.xy - resolution / 2) * vec2(1.0, aspect_ratio) / resolution;
+
+ vec3 color = image(uv);
color = clamp(color, 0, 1);
imageStore(output_image, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1));
}
diff --git a/src/main/resources/shaders/time.glsl b/src/main/resources/shaders/time.glsl
new file mode 100644
index 0000000..1c22e12
--- /dev/null
+++ b/src/main/resources/shaders/time.glsl
@@ -0,0 +1,147 @@
+#version 430
+layout(local_size_x = 1, local_size_y = 1) in;
+
+#include <sdf>
+#include <utils>
+#include <noise>
+
+#define PI 3.14159265358979323
+
+uniform float hours = 0;
+uniform float minutes = 0;
+uniform float seconds = 0;
+uniform float time = 0;
+layout(rgba8) uniform readonly image2D noise_texture;
+layout(rgba8) uniform readonly image2D text_texture;
+layout(rgba8) uniform writeonly image2D output_image;
+
+uniform float antialiasing = 0.28;
+uniform bool enable_antialiasing = false;
+
+float sample_noise(in vec2 p) {
+ vec4 noise = imageLoad(noise_texture, ivec2((p + 0.5) * imageSize(noise_texture)));
+ return noise.x;
+}
+
+float blink_easing(in float x) {
+ return x < 0.5 ? 8 * x * x * x * x : 1 - pow(-2 * x + 2, 4) / 2;
+}
+
+float digit(in vec2 uv, in int digit, in float size) {
+ vec2 p = uv * 5000 / size;
+ float digitSize = imageSize(text_texture).x / 10.;
+ float digitOffset = digitSize * digit;
+ p.x = clamp(p.x + digitOffset, digitOffset, digitOffset + digitSize);
+ vec4 s = imageLoad(text_texture, ivec2(p));
+ return s.w;
+}
+
+vec3 image(in vec2 uv) {
+ const vec3 eye_color = srgb(1, 1, 1);
+ const vec3 iris_color = srgb(0.2, 0.1, 0.1);
+ const vec3 pupil_color = srgb(0, 0, 0);
+ const vec3 skin_color = srgb(0.14, 0.03, 0.14);
+ // const vec3 skin_color = mix(srgb(0.94, 0.75, 0.65), vec3(0), 0.9);
+ const vec3 bloodvessel_color = srgb(0.89, 0.12, 0.06);
+ const vec3 clockdigit_color = mix(bloodvessel_color, vec3(0), 0.1);
+
+ vec3 color = bloodvessel_color;
+
+ {
+ float eye = sdf_circle(uv, 0.41 * (1 - 0.08 * fbm(100 * uv)));
+ vec3 eyeball_color = eye_color;
+ float veins = sin((uv.y + 1) * 260 * sin((uv.x + 1) * 0.1) * fbm(uv * 20)) + 0.98;
+ eyeball_color = mix(eyeball_color, bloodvessel_color, mix(0, step(veins, 0), clamp(sample_noise(uv) - 0.1, 0, 1)));
+ eyeball_color = mix(eyeball_color, vec3(0), (0.2 - uv.x) * (1.3 - uv.y));
+ color = mix(color, eyeball_color, step(eye, 0));
+ }
+
+ {
+ float iris = sdf_circle(uv, 0.144);
+ color = mix(color, iris_color, step(iris, 0));
+ float angle = 50 * (atan(uv.y, uv.x)) + 10.0 * fbm(uv * 100);
+ float irispat = max(iris, sin(angle));
+ color = mix(color, vec3(0), 0.6 * step(irispat, 0));
+ }
+
+ {
+ float angle = PI / 2 - hours * PI / 6 - minutes * PI / (12 * 60);
+ vec2 offset = 0.10 * vec2(cos(angle), sin(angle));
+ float iris_spec = sdf_circle((uv - offset) * vec2(0.8, 1.0), 0.010);
+ color = mix(color, vec3(1), step(iris_spec, 0));
+ }
+ {
+ float angle = PI / 2 - minutes * PI / 30;
+ vec2 offset = 0.148 * vec2(cos(angle), sin(angle));
+ float iris_spec = sdf_circle(uv - offset, 0.005);
+ color = mix(color, iris_color, step(iris_spec, 0));
+ }
+
+ {
+ float pupil = sdf_circle(uv, 0.04);
+ color = mix(color, pupil_color, step(pupil, 0));
+ }
+
+ {
+ // TODO: Switch to domain repetition
+ for (int i = 0; i < 12; i++) {
+ float theta = PI / 6.;
+ float r = 0.17;
+ vec2 digitpos = uv + vec2(0.011, 0.034) - r * vec2(cos(-i * theta + PI / 3), sin(-i * theta + PI / 3));
+ digitpos *= (1 + 0.8 * fbm(60 * uv));
+ float digit_size = 1.6;
+ float s = 0;
+ if (i + 1 >= 10) {
+ s = digit(digitpos + vec2(0.01, 0), 1, digit_size);
+ digitpos.x -= 0.01;
+ }
+ s = max(s, digit(digitpos, (i + 1) % 10, digit_size));
+ color = mix(color, clockdigit_color, s);
+ }
+ }
+
+ float eye_open_factor = 0.092;
+ float eyehole_factor = 0.136;
+ float eyelid_size = 4;
+ vec2 eyep = uv;
+ {
+ float blinkduration = 0.6;
+ float blink_every = 8;
+ float blinkt = mod(time, blink_every) * 2 / blinkduration;
+ int should_blink = int(mod(time, blink_every) < blinkduration);
+ float blink = blink_easing(mod(blinkt, 1));
+ blink = mix(1 - blink, blink, clamp(int(blinkt) % 2, 0., 1.));
+ float a = mix(0, eye_open_factor, mix(1, blink, should_blink));
+ float eyelid = a * cos(eyelid_size * eyep.x / 2 * PI) - abs(eyep.y) + a;
+ float eyehole = eyehole_factor * cos((eyelid_size / 1.16) * eyep.x / 2 * PI) - abs(eyep.y) + eyehole_factor;
+ vec3 eyelid_color = skin_color;
+ vec3 patterning = mix(srgb(1, 0, 0), srgb(1, 0.46, 0), pow(sin(eyep.x * 16 + 100 * fbm(vec3(uv * 10, time / 20), 3)), 2));
+ float patnoise = smoothstep(-eyelid, 0, 0.028 * fbm(uv * 100));
+ eyelid_color = mix(eyelid_color, patterning, 1 - clamp(patnoise, 0, 1));
+ eyelid_color = mix(eyelid_color, vec3(0), 1 - step(eyelid + 0.004, 0));
+ color = mix(color, eyelid_color, step(eyelid, 0));
+ }
+
+ 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);
+ 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));
+}