diff --git a/.gitignore b/.gitignore index cb00cbb9..f567a4bf 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ build bin .project .classpath +juliaOcean +juliaSin # Ignore core dupmps .log diff --git a/README.md b/README.md index 7567e837..29dec038 100644 --- a/README.md +++ b/README.md @@ -46,4 +46,20 @@ Included Foton library provides a clean and fun way to animate functions and ray +### Reduce GPU resulltion +To reduce the GPU resolution during rendering, you can adjust the parameters passed to the ``AnimatedFunctionRenderer((Parameters(1024, 1024, 30)))`` eg: 1024 to 512 + +### Render the frames + 1. Install `ffmpeg` if you haven't already. + 2. Render to MP4: + +Render to MP4 : + + ``ffmpeg -framerate 30 -i frame%02d.png -vf "scale=540:540" -c:v libx264 -pix_fmt yuv420p output_video.mp4`` + + 3. Render to GIF: + +Renderto to Gif + +``ffmpeg -t 3 -i output_video.mp4 -vf "fps=30,scale=720:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 output_git.gif`` diff --git a/build.sbt b/build.sbt index be3ae143..471eea55 100644 --- a/build.sbt +++ b/build.sbt @@ -55,6 +55,6 @@ lazy val root = (project in file(".")) ) ) -lazy val vulkanSdk = System.getenv("VULKAN_SDK") -javaOptions += s"-Dorg.lwjgl.vulkan.libname=$vulkanSdk/lib/libvulkan.1.dylib" +// lazy val vulkanSdk = System.getenv("VULKAN_SDK") +// javaOptions += s"-Dorg.lwjgl.vulkan.libname=$vulkanSdk/lib/libvulkan.1.dylib" diff --git a/finalGif/Ocean/frame03.png b/finalGif/Ocean/frame03.png new file mode 100644 index 00000000..1b35f9ed Binary files /dev/null and b/finalGif/Ocean/frame03.png differ diff --git a/finalGif/Ocean/frame04.png b/finalGif/Ocean/frame04.png new file mode 100644 index 00000000..ac0d8015 Binary files /dev/null and b/finalGif/Ocean/frame04.png differ diff --git a/finalGif/Ocean/frame05.png b/finalGif/Ocean/frame05.png new file mode 100644 index 00000000..90a024fd Binary files /dev/null and b/finalGif/Ocean/frame05.png differ diff --git a/finalGif/Ocean/frame52.png b/finalGif/Ocean/frame52.png new file mode 100644 index 00000000..a4679ac3 Binary files /dev/null and b/finalGif/Ocean/frame52.png differ diff --git a/finalGif/Ocean/frame69.png b/finalGif/Ocean/frame69.png new file mode 100644 index 00000000..3385bcc1 Binary files /dev/null and b/finalGif/Ocean/frame69.png differ diff --git a/finalGif/Ocean/julaiOcean.gif b/finalGif/Ocean/julaiOcean.gif new file mode 100644 index 00000000..d2a7041f Binary files /dev/null and b/finalGif/Ocean/julaiOcean.gif differ diff --git a/finalGif/Sin/frame00.png b/finalGif/Sin/frame00.png new file mode 100644 index 00000000..e1c06e45 Binary files /dev/null and b/finalGif/Sin/frame00.png differ diff --git a/finalGif/Sin/frame30.png b/finalGif/Sin/frame30.png new file mode 100644 index 00000000..62537ce7 Binary files /dev/null and b/finalGif/Sin/frame30.png differ diff --git a/finalGif/Sin/frame50.png b/finalGif/Sin/frame50.png new file mode 100644 index 00000000..d279d57e Binary files /dev/null and b/finalGif/Sin/frame50.png differ diff --git a/finalGif/Sin/julaiSin.gif b/finalGif/Sin/julaiSin.gif new file mode 100644 index 00000000..824eb221 Binary files /dev/null and b/finalGif/Sin/julaiSin.gif differ diff --git a/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJuliaOceanDress.scala b/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJuliaOceanDress.scala new file mode 100644 index 00000000..c2d5c942 --- /dev/null +++ b/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJuliaOceanDress.scala @@ -0,0 +1,44 @@ +package io.computenode.cyfra.samples.foton + +import io.computenode.cyfra +import io.computenode.cyfra.* +import io.computenode.cyfra.dsl.Algebra.{*, given} +import io.computenode.cyfra.dsl.Functions.* +import io.computenode.cyfra.dsl.GSeq +import io.computenode.cyfra.dsl.Value.* +import io.computenode.cyfra.foton.animation.AnimatedFunctionRenderer.Parameters +import io.computenode.cyfra.foton.animation.AnimationFunctions.* +import io.computenode.cyfra.foton.animation.{AnimatedFunction, AnimatedFunctionRenderer} +import io.computenode.cyfra.utility.Color.* +import io.computenode.cyfra.utility.Math3D.* + +import scala.concurrent.duration.DurationInt +import java.nio.file.Paths + +object AnimatedJuliaOcean: + @main + def juliaOcean() = + + def juliaOcean(uv: Vec2[Float32])(using AnimationInstant): Int32 = + val p = smooth(from = 0.355f, to = 0.4f, duration = 3.seconds) + val const = (p, p) + GSeq.gen(uv, next = v => { + ((v.x * v.x) - (v.y * v.y), 2.0f * v.x * v.y) + const + }).limit(1000).map(length).takeWhile(_ < 2.0f).count + + def juliaOceanColor(uv: Vec2[Float32])(using AnimationInstant): Vec4[Float32] = + val rotatedUv = rotate(uv, Math.PI.toFloat / 3.0f) + val recursionCount = juliaOcean(rotatedUv) + val f = min(1f, recursionCount.asFloat / 100f) + val color = interpolate(InterpolationThemes.Ocean, f) + ( + color.r, + color.g, + color.b, + 1.0f + ) + + val animatedJuliaOcean = AnimatedFunction.fromCoord(juliaOceanColor, 3.seconds) + + val renderer = AnimatedFunctionRenderer(Parameters(1024, 1024, 30)) // Reduce resolution if our GPU is not capabale + renderer.renderFramesToDir(animatedJuliaOcean, Paths.get("juliaOcean")) diff --git a/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJuliaSin.scala b/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJuliaSin.scala new file mode 100644 index 00000000..31e12add --- /dev/null +++ b/src/main/scala/io/computenode/cyfra/samples/foton/AnimatedJuliaSin.scala @@ -0,0 +1,55 @@ +package io.computenode.cyfra.samples.foton + +import io.computenode.cyfra +import io.computenode.cyfra.* +import io.computenode.cyfra.dsl.Algebra.{*, given} +import io.computenode.cyfra.dsl.Functions.* +import io.computenode.cyfra.dsl.GSeq +import io.computenode.cyfra.dsl.Value.* +import io.computenode.cyfra.foton.animation.AnimatedFunctionRenderer.Parameters +import io.computenode.cyfra.foton.animation.AnimationFunctions.* +import io.computenode.cyfra.foton.animation.{AnimatedFunction, AnimatedFunctionRenderer} +import io.computenode.cyfra.utility.Color.* +import io.computenode.cyfra.utility.Math3D.* + +import scala.concurrent.duration.DurationInt +import java.nio.file.Paths + +object AnimatedJuliaSin: + @main + def juliaSin() = + + def juliaSin(uv: Vec2[Float32])(using AnimationInstant): Int32 = + val p = smooth(from = 0.355f, to = 0.4f, duration = 3.seconds) + val const = (p, p) + GSeq.gen(uv, next = v => { + // Define the Julia set transformation here + ((v.x * v.x ) - (v.y * v.y), 2.0f * v.x * v.y) + const + }).limit(1000).map(length).takeWhile(_ < 2.0f).count + + def juliaSinColor(uv: Vec2[Float32])(using AnimationInstant): Vec4[Float32] = + val rotatedUv = rotate(uv, Math.PI.toFloat / 3.0f) + val recursionCount = juliaSin(rotatedUv) + val f = min(1f, recursionCount.asFloat / 100f) + + val brightness = vec3(0.5f, 0.5f, 0.5f) // Adjust as needed + val contrast = vec3(0.5f, 0.5f, 0.5f) // Increase for more vivid colors + val freq = vec3(3.0f, 2.0f, 1.0f) // Controls the color cycling + val offsets = vec3(0.0f, 0.5f, 1.0f) // Phase offsets for R, G, B + + val color1 = igPallette(brightness, contrast, freq, offsets, f) + ( + color1.r, + color1.g, + color1.b, + 1.0f + ) + + val animatedJuliaSin = AnimatedFunction.fromCoord(juliaSinColor, 3.seconds) + + val renderer = AnimatedFunctionRenderer(Parameters(1024, 1024, 30)) // Reduce resolution if our GPU is not capabale + renderer.renderFramesToDir(animatedJuliaSin, Paths.get("juliaSin")) + +// ffmpeg -framerate 30 -i frame%02d.png -vf "scale=540:540" -c:v libx264 -pix_fmt yuv420p output_video6.mp4 + +// ffmpeg -t 3 -i output_video.mp4 -vf "fps=30,scale=720:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 julaiSin.gif \ No newline at end of file diff --git a/src/main/scala/io/computenode/cyfra/utility/Color.scala b/src/main/scala/io/computenode/cyfra/utility/Color.scala index e8e99a4a..2da6ccbc 100644 --- a/src/main/scala/io/computenode/cyfra/utility/Color.scala +++ b/src/main/scala/io/computenode/cyfra/utility/Color.scala @@ -43,6 +43,13 @@ object Color: object InterpolationThemes: val Blue: InterpolationTheme = ((8f, 22f, 104f) * (1 / 255f), (62f, 82f, 199f) * (1 / 255f), (221f, 233f, 255f) * (1 / 255f)) val Black: InterpolationTheme = ((255f, 255f, 255f) * (1 / 255f), (0f, 0f, 0f), (0f, 0f, 0f)) + val Red: InterpolationTheme = ((120f, 20f, 20f) * (1 / 255f), (200f, 40f, 40f) * (1 / 255f), (255f, 150f, 150f) * (1 / 255f)) + val Green: InterpolationTheme = ((10f, 50f, 10f) * (1 / 255f), (50f, 160f, 50f) * (1 / 255f), (180f, 255f, 180f) * (1 / 255f)) + val Purple: InterpolationTheme = ((50f, 0f, 50f) * (1 / 255f), (128f, 0f, 128f) * (1 / 255f), (255f, 150f, 255f) * (1 / 255f)) + val Fire: InterpolationTheme = ((120f, 40f, 0f) * (1 / 255f), (255f, 85f, 0f) * (1 / 255f), (255f, 200f, 50f) * (1 / 255f)) + val Ocean: InterpolationTheme = ((0f, 32f, 64f) * (1 / 255f), (0f, 128f, 192f) * (1 / 255f), (128f, 224f, 255f) * (1 / 255f)) + val Sunset: InterpolationTheme = ((255f, 94f, 77f) * (1 / 255f), (255f, 168f, 77f) * (1 / 255f), (255f, 239f, 161f) * (1 / 255f)) + val Ice: InterpolationTheme = ((0f, 100f, 200f) * (1 / 255f), (100f, 200f, 255f) * (1 / 255f), (230f, 255f, 255f) * (1 / 255f)) def interpolate(theme: InterpolationTheme, f: Float32): Vec3[Float32] = val (c1, c2, c3) = theme