From 5f41d4cded56121af66b18c232c7f557ab803f94 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Sun, 27 Sep 2026 12:06:00 +0530 Subject: Add headless screenshot + fix scaling for antialiasing for vacation --- src/main/kotlin/org/openrndr/Preload.kt | 7 +- src/main/kotlin/phenax/extensions/CameraManager.kt | 6 +- .../kotlin/phenax/extensions/HeadlessScreenshot.kt | 30 +++++ src/main/kotlin/phenax/utils/program.kt | 7 +- src/main/kotlin/seigaiha/SeigaihaProgram.kt | 2 +- src/main/kotlin/vacation/VacationProgram.kt | 16 ++- src/main/resources/shaders/vacation.glsl | 133 +++++++++++---------- 7 files changed, 129 insertions(+), 72 deletions(-) create mode 100644 src/main/kotlin/phenax/extensions/HeadlessScreenshot.kt (limited to 'src') diff --git a/src/main/kotlin/org/openrndr/Preload.kt b/src/main/kotlin/org/openrndr/Preload.kt index 1bbd673..9664416 100644 --- a/src/main/kotlin/org/openrndr/Preload.kt +++ b/src/main/kotlin/org/openrndr/Preload.kt @@ -1,14 +1,19 @@ package org.openrndr import org.openrndr.draw.* +import org.openrndr.extensions.Screenshots +import org.openrndr.extra.olive.* import phenax.extensions.HeadlessRecorder -import phenax.utils.recordingEnabled +import phenax.extensions.HeadlessScreenshot +import phenax.utils.* class Preload : ApplicationPreload() { override fun onProgramSetup(program: Program) { println("BACKEND(${program.name}): ${program.application::class.qualifiedName}") if (recordingEnabled) { program.extend(HeadlessRecorder()) + } else if (screenshotEnabled) { + program.extend(HeadlessScreenshot()) } } } diff --git a/src/main/kotlin/phenax/extensions/CameraManager.kt b/src/main/kotlin/phenax/extensions/CameraManager.kt index d14205f..5112332 100644 --- a/src/main/kotlin/phenax/extensions/CameraManager.kt +++ b/src/main/kotlin/phenax/extensions/CameraManager.kt @@ -7,7 +7,7 @@ import org.openrndr.draw.* import org.openrndr.math.Quaternion import org.openrndr.math.Vector2 import org.openrndr.math.Vector3 -import phenax.utils.recordingEnabled +import phenax.utils.* enum class ActionType { PAN, @@ -35,7 +35,7 @@ class CameraManager(public var cameraPosition: Vector3, public var cameraRotatio } override fun setup(program: Program) { - if (recordingEnabled) return + if (recordingEnabled || screenshotEnabled) return cameraQuaternion = Quaternion.fromAngles(cameraRotation.x, cameraRotation.y, cameraRotation.z) @@ -99,7 +99,7 @@ class CameraManager(public var cameraPosition: Vector3, public var cameraRotatio override fun beforeDraw(drawer: Drawer, program: Program) {} override fun afterDraw(drawer: Drawer, program: Program) { - if (recordingEnabled) return + if (recordingEnabled || screenshotEnabled) return drawer.fontMap = font drawer.fill = ColorRGBa.WHITE diff --git a/src/main/kotlin/phenax/extensions/HeadlessScreenshot.kt b/src/main/kotlin/phenax/extensions/HeadlessScreenshot.kt new file mode 100644 index 0000000..35de05d --- /dev/null +++ b/src/main/kotlin/phenax/extensions/HeadlessScreenshot.kt @@ -0,0 +1,30 @@ +package phenax.extensions + +import org.openrndr.* +import org.openrndr.draw.* +import org.openrndr.extensions.SingleScreenshot +import org.openrndr.ffmpeg.VideoWriter + +class HeadlessScreenshot : Extension { + override var enabled: Boolean = true + + var screenshots: SingleScreenshot? = null + var videoWriter: VideoWriter? = null + var maxFrameCount: Int? = null + + override fun setup(program: Program) { + val scr = SingleScreenshot() + screenshots = scr + program.extend(scr) { + outputFile = "screenshot/${program.name}.png" + } + } + + override fun beforeDraw(drawer: Drawer, program: Program) {} + + override fun afterDraw(drawer: Drawer, program: Program) { + screenshots?.trigger() + + // program.application.exit() + } +} diff --git a/src/main/kotlin/phenax/utils/program.kt b/src/main/kotlin/phenax/utils/program.kt index fe48351..cfbe9c9 100644 --- a/src/main/kotlin/phenax/utils/program.kt +++ b/src/main/kotlin/phenax/utils/program.kt @@ -19,7 +19,8 @@ fun recordDuration(millis: Int) { fun recordDuration(): Int? = System.getProperty("phenax.record.frameCount")?.toIntOrNull() -val recordingEnabled: Boolean by lazy { System.getenv("RECORD") != null } +val recordingEnabled: Boolean by lazy { System.getenv("PHENAX_RECORD") != null } +val screenshotEnabled: Boolean by lazy { System.getenv("PHENAX_SCREENSHOT") != null } // fun classDir(): String = // "src/main/kotlin/${stackRootClassName(sanitize = @@ -30,7 +31,7 @@ val recordingEnabled: Boolean by lazy { System.getenv("RECORD") != null } // Have to keep the same name (oliveProgram) to get update on save to work fun ApplicationBuilder.oliveProgram(init: Program.() -> Unit) { - if (recordingEnabled) { + if (recordingEnabled || screenshotEnabled) { program(init) } else { // TODO: Make watching shader files work @@ -88,7 +89,7 @@ fun Program.liveComputeShader(name: String): ReadOnlyProperty