aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2026-09-24 11:53:12 +0530
committerAkshay Nair <phenax5@gmail.com>2026-09-24 11:53:12 +0530
commitdc29499b23a90fac438cf74eb4865c15afecbdbd (patch)
tree4ef563c2611074ba58d59a54c4af231ec32512bb /src
parent7bdd84e8ecade87ececdefe3cee614df8438e0a1 (diff)
downloadart-playground-openrndr-dc29499b23a90fac438cf74eb4865c15afecbdbd.tar.gz
art-playground-openrndr-dc29499b23a90fac438cf74eb4865c15afecbdbd.zip
Door thingy
Diffstat (limited to 'src')
-rw-r--r--src/main/kotlin/mrdoor/MrdoorProgram.kt36
-rw-r--r--src/main/kotlin/phenax/extensions/CameraManager.kt7
-rw-r--r--src/main/resources/shaders/modules/utils.glsl6
-rw-r--r--src/main/resources/shaders/mrdoor.glsl169
4 files changed, 218 insertions, 0 deletions
diff --git a/src/main/kotlin/mrdoor/MrdoorProgram.kt b/src/main/kotlin/mrdoor/MrdoorProgram.kt
new file mode 100644
index 0000000..deabfe3
--- /dev/null
+++ b/src/main/kotlin/mrdoor/MrdoorProgram.kt
@@ -0,0 +1,36 @@
+package mrdoor
+
+import org.openrndr.application
+import org.openrndr.color.*
+import org.openrndr.draw.*
+import org.openrndr.math.*
+import phenax.extensions.CameraManager
+import phenax.utils.*
+
+fun main() = application {
+ recordDuration(5.seconds())
+
+ configure {
+ width = 640
+ height = 480
+ windowResizable = false
+ }
+
+ 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 outputBuffer = colorBuffer(width, height, type = ColorType.UINT8)
+
+ extend {
+ cs.uniform("seconds", seconds)
+ 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/phenax/extensions/CameraManager.kt b/src/main/kotlin/phenax/extensions/CameraManager.kt
index 0303a54..d14205f 100644
--- a/src/main/kotlin/phenax/extensions/CameraManager.kt
+++ b/src/main/kotlin/phenax/extensions/CameraManager.kt
@@ -26,6 +26,13 @@ class CameraManager(public var cameraPosition: Vector3, public var cameraRotatio
var lastPos: Vector3? = null
constructor() : this(Vector3(0.0, 1.0, 0.0), Vector3.ZERO) {}
+ constructor(
+ cameraPosition: Vector3,
+ cameraRotation: Vector3,
+ lightPos: Vector3
+ ) : this(cameraPosition, cameraRotation) {
+ lightPosition = lightPos
+ }
override fun setup(program: Program) {
if (recordingEnabled) return
diff --git a/src/main/resources/shaders/modules/utils.glsl b/src/main/resources/shaders/modules/utils.glsl
index 6908f3b..3520df1 100644
--- a/src/main/resources/shaders/modules/utils.glsl
+++ b/src/main/resources/shaders/modules/utils.glsl
@@ -7,3 +7,9 @@ float ssubtract(float a, float b, float k) {
return -smin(-a, b, k);
}
+vec3 srgb(float r, float g, float b) {
+ return vec3(pow(r, 2.2), pow(g, 2.2), pow(b, 2.2));
+}
+vec3 srgb(vec3 c) {
+ return srgb(c.r, c.g, c.b);
+}
diff --git a/src/main/resources/shaders/mrdoor.glsl b/src/main/resources/shaders/mrdoor.glsl
new file mode 100644
index 0000000..06733c6
--- /dev/null
+++ b/src/main/resources/shaders/mrdoor.glsl
@@ -0,0 +1,169 @@
+#version 430
+layout(local_size_x = 1, local_size_y = 1) in;
+
+#include <sdf>
+#include <utils>
+#include <noise>
+
+uniform float seconds = 0;
+uniform vec3 camera_position = vec3(0, 1, 0);
+uniform mat3 camera_transformation;
+uniform vec3 key_light_position;
+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);
+
+#define PI 3.14159265358979323
+
+struct Obj {
+ int objid;
+ float dist;
+ vec3 material;
+ bool lighting;
+ float shine;
+};
+
+Obj null_object = Obj(-1, -1.0, vec3(0.01), false, 0.0); // 0.35, 0.6, 0.9
+Obj create_obj(in int objid, in float dist) {
+ return Obj(objid, dist, vec3(1), true, 0.0);
+}
+
+Obj scene(in vec3 p) {
+ vec3 doorpos = p - vec3(-0.5, 1.4, 5);
+ vec3 doorsize = vec3(1., 2., 0.1);
+
+ float doorbody = sdf_box(doorpos, doorsize, 0.04);
+ doorbody = ssubtract(doorbody, sdf_box(doorpos - vec3(0, 1.1, -0.2), vec3(0.65, 0.5, 0.1), 0), 0.1);
+ doorbody = ssubtract(doorbody, sdf_box(doorpos - vec3(0, -0.75, -0.2), vec3(0.65, 0.85, 0.1), 0), 0.1);
+ Obj doorhandle = create_obj(2, sdf_circle(doorpos - vec3(0.75, 0.34, -0.3), 0.1));
+ doorhandle.material = vec3(0.4, 0.4, 0.4);
+ doorhandle.shine = 22.0;
+ Obj door = create_obj(2, doorbody);
+ door.material = vec3(0.68, 0.17, 0.20);
+ door.shine = 2.0;
+
+ float doorframe = ssubtract(
+ sdf_box(doorpos - vec3(0, 0.5, 0), vec3(2., 2.6, 0.1), 0),
+ sdf_box(doorpos, doorsize + vec3(0.01, 0.01, 0.04), 0), 0.0);
+ vec3 wallpos = doorpos;
+ wallpos.xz *= mat2x2(cos(PI / 2.), -sin(PI / 2.), sin(PI / 2.), cos(PI / 2.));
+ float wallsides = min(
+ sdf_box(wallpos - vec3(0, 0.5, -2), vec3(2., 2.6, 0.08), 0),
+ sdf_box(wallpos - vec3(0, 0.5, 2), vec3(2., 2.6, 0.08), 0));
+ float roof = sdf_box(doorpos - vec3(0, 3.3, -2), vec3(2., 0.08, 2.6), 0);
+ Obj walls = create_obj(2, min(min(doorframe, wallsides), roof));
+ walls.material = vec3(0.15, 0.28, 0.42);
+
+ Obj debugdot = create_obj(-1, sdf_circle(p - door1_light_position, 0.1));
+ debugdot.lighting = false;
+ debugdot.material = vec3(0, 1, 0);
+
+ Obj floor = create_obj(0, sdf_plane(p - vec3(0, -0.6, 0), vec3(0, 1, 0), 0.0));
+ floor.material = vec3(0.4);
+ float dist = floor.dist;
+ dist = min(door.dist, dist);
+ dist = min(doorhandle.dist, dist);
+ dist = min(walls.dist, dist);
+ dist = min(debugdot.dist, dist);
+ if (dist == door.dist) return door;
+ if (dist == doorhandle.dist) return doorhandle;
+ if (dist == floor.dist) return floor;
+ if (dist == walls.dist) return walls;
+ if (dist == debugdot.dist) return debugdot;
+ return null_object;
+}
+
+#define RM_SHADOW_MAX_ITERATIONS 100
+#define RM_MAX_ITERATIONS 300
+#define RM_MAX_DISTANCE 80
+
+Obj ray_march_scene(in vec3 ray_origin, in vec3 ray_direction) {
+ float dist = 0;
+ for (int i = 0; i < RM_MAX_ITERATIONS && dist < RM_MAX_DISTANCE; i++) {
+ vec3 p = ray_origin + ray_direction * dist;
+ Obj o = scene(p);
+ dist += o.dist;
+ if (o.dist <= 0.01) {
+ o.dist = dist;
+ return o;
+ }
+ }
+ return null_object;
+}
+
+vec3 surface_normal_scene(in vec3 p) {
+ vec2 e = vec2(0.01, 0);
+ return normalize(vec3(
+ scene(p + e.xyy).dist - scene(p - e.xyy).dist,
+ scene(p + e.yxy).dist - scene(p - e.yxy).dist,
+ scene(p + e.yyx).dist - scene(p - e.yyx).dist));
+}
+
+float shadow_scene(in vec3 ray_origin, in vec3 ray_direction, in float light_intensity) {
+ float dist = 0.015;
+ float res = 1.;
+ float prev_gap = 1e10;
+ for (int i = 0; i < RM_SHADOW_MAX_ITERATIONS && dist < RM_MAX_DISTANCE; i++) {
+ vec3 p = ray_origin + dist * ray_direction;
+ Obj obj = scene(p);
+ float gap = obj.dist;
+ if (!obj.lighting)
+ continue;
+ float y = gap * gap / (10000.0 * prev_gap);
+ float d = sqrt(abs(gap * gap - y * y));
+ res = min(res, light_intensity * d / max(0, dist - y));
+ prev_gap = gap;
+ dist += gap;
+
+ if (res < 0.0001)
+ break;
+ }
+
+ res = clamp(res * 1.1, 0.18, 1.0);
+ 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 origin = vec3(0);
+ vec3 uv_direction = normalize((vec3(uv.x, uv.y, 1) - origin) * camera_transformation + origin);
+
+ Obj obj = ray_march_scene(camera_position, uv_direction);
+ vec3 p = camera_position + uv_direction * obj.dist;
+ vec3 normal = surface_normal_scene(p);
+
+ vec3 color = srgb(obj.material);
+
+ if (obj.lighting) {
+ float ambient = 0.03;
+
+ vec3 keyl_dir = normalize(key_light_position - p);
+ float key_contrast = 1.;
+ key_contrast *= clamp(dot(normal, keyl_dir), 0, 1);
+ 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);
+
+ float 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 *
+ (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);
+ }
+
+ color = clamp(color, 0, 1);
+ imageStore(output_image, ivec2(gl_GlobalInvocationID.xy), vec4(color, 1));
+}