From dc29499b23a90fac438cf74eb4865c15afecbdbd Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Thu, 24 Sep 2026 11:53:12 +0530 Subject: Door thingy --- src/main/kotlin/mrdoor/MrdoorProgram.kt | 36 +++++ src/main/kotlin/phenax/extensions/CameraManager.kt | 7 + src/main/resources/shaders/modules/utils.glsl | 6 + src/main/resources/shaders/mrdoor.glsl | 169 +++++++++++++++++++++ 4 files changed, 218 insertions(+) create mode 100644 src/main/kotlin/mrdoor/MrdoorProgram.kt create mode 100644 src/main/resources/shaders/mrdoor.glsl (limited to 'src') 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 +#include +#include + +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)); +} -- cgit v1.3.1