diff options
| author | Akshay Nair <phenax5@gmail.com> | 2026-10-01 15:00:35 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2026-10-01 15:00:35 +0530 |
| commit | b04c4008e73d1515d1f78f993ca25826847d7207 (patch) | |
| tree | e884360817b047eae4db05e36595a0c7f40a1399 | |
| parent | 0fc4f3de01b6ef63e1fc8d36d581a542b3c27a42 (diff) | |
| download | art-playground-openrndr-b04c4008e73d1515d1f78f993ca25826847d7207.tar.gz art-playground-openrndr-b04c4008e73d1515d1f78f993ca25826847d7207.zip | |
Add time
| -rw-r--r-- | src/main/kotlin/mrdoor/MrdoorProgram.kt | 8 | ||||
| -rw-r--r-- | src/main/kotlin/time/TimeProgram.kt | 78 | ||||
| -rw-r--r-- | src/main/resources/shaders/mrdoor.glsl | 67 | ||||
| -rw-r--r-- | src/main/resources/shaders/time.glsl | 147 |
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)); +} |
