-
-
Save ricardomatias/b7cf2de2d8ed0f20918ac5477c1503a1 to your computer and use it in GitHub Desktop.
StripedTube: code for https://www.instagram.com/p/CGYBXZNHTJk/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package org.ygl.openrndr.demos | |
| import org.openrndr.application | |
| import org.openrndr.color.ColorRGBa | |
| import org.openrndr.draw.BufferMultisample | |
| import org.openrndr.draw.DrawPrimitive | |
| import org.openrndr.draw.colorBuffer | |
| import org.openrndr.draw.renderTarget | |
| import org.openrndr.draw.shadeStyle | |
| import org.openrndr.draw.vertexBuffer | |
| import org.openrndr.draw.vertexFormat | |
| import org.openrndr.extra.compositor.compose | |
| import org.openrndr.extra.compositor.draw | |
| import org.openrndr.extra.compositor.post | |
| import org.openrndr.extra.fx.blur.FrameBlur | |
| import org.openrndr.extra.parameters.Description | |
| import org.openrndr.extra.parameters.DoubleParameter | |
| import org.openrndr.extras.camera.OrbitalCamera | |
| import org.openrndr.extras.camera.OrbitalControls | |
| import org.openrndr.extras.camera.applyTo | |
| import org.openrndr.ffmpeg.VideoWriter | |
| import org.openrndr.math.Vector2 | |
| import org.openrndr.math.Vector3 | |
| import org.openrndr.math.mix | |
| import org.openrndr.math.transforms.transform | |
| import org.ygl.fastnoise.FastNoise | |
| import org.ygl.kxa.ease.Ease | |
| import org.ygl.openrndr.utils.isolatedWithTarget | |
| import kotlin.math.PI | |
| import kotlin.math.cos | |
| import kotlin.math.sin | |
| private const val WIDTH = 920 | |
| private const val HEIGHT = 920 | |
| private const val TOTAL_FRAMES = 360 | |
| private const val LOOPS = 1 | |
| private const val DELAY_FRAMES = 120 | |
| private const val RECORDING = true | |
| fun main() = application { | |
| configure { | |
| width = WIDTH | |
| height = HEIGHT | |
| } | |
| program { | |
| var time = 0.0 | |
| val smallRadius = 50.0 | |
| val bigRadius = 300.0 | |
| val noise = FastNoise() | |
| val camera = OrbitalCamera( | |
| eye = Vector3(0.0, 15.0, -bigRadius), | |
| lookAt = Vector3(0.0, -230.0, 270.0), | |
| fov = 60.0 | |
| ) | |
| val widthSegments = 90 | |
| val heightSegments = 180 | |
| val meshData = List(heightSegments) { | |
| MutableList(widthSegments) { Vector3.ZERO } | |
| } | |
| val vb = vertexBuffer(vertexFormat { | |
| position(3) | |
| textureCoordinate(2) | |
| }, widthSegments * heightSegments * 6) | |
| val params = @Description("params") object { | |
| @DoubleParameter("noise mag", 0.0, 100.0, precision = 2) | |
| var mag = 10.0 | |
| @DoubleParameter("noise scale x", 0.0, 20.0, precision = 2) | |
| var scaleX = 2.5 | |
| @DoubleParameter("noise scale y", 0.0, 20.0, precision = 2) | |
| var scaleY = 3.5 | |
| @DoubleParameter("noise radius", 0.0, 100.0, precision = 2) | |
| var rad = 60.0 | |
| } | |
| fun update() { | |
| time = ((frameCount - 1) % TOTAL_FRAMES) / TOTAL_FRAMES.toDouble() | |
| camera.update(deltaTime) | |
| for (row in 0 until heightSegments) { | |
| var rowProgress = row / (heightSegments - 1.0) | |
| for (col in 0 until widthSegments) { | |
| val colProgress = col / (widthSegments - 1.0) | |
| rowProgress = Ease.NONE(rowProgress) | |
| val tubeWidth = smallRadius | |
| val x = -tubeWidth + 2 * tubeWidth * (colProgress) | |
| noise.seed = 1 | |
| val radiusNoiseValue = params.mag * noise.getSimplex( | |
| params.scaleX * x, | |
| params.scaleY * params.rad * sin(2 * PI * (time - rowProgress)), | |
| params.scaleY * params.rad * cos(2 * PI * (time - rowProgress)), | |
| ) | |
| val noisyRadius = -smallRadius + radiusNoiseValue * rowProgress | |
| noise.seed = 2 | |
| val angleNoiseValue = 0.1 * rowProgress * noise.getSimplex( | |
| params.scaleX * x, | |
| params.scaleY * params.rad * sin(2 * PI * (time - rowProgress)), | |
| params.scaleY * params.rad * cos(2 * PI * (time - rowProgress)), | |
| ) | |
| val z = mix(0.0, noisyRadius * sin(PI * (colProgress + angleNoiseValue)), rowProgress) | |
| val pos = transform { | |
| rotate(Vector3.UNIT_X, 90.0 * rowProgress) | |
| translate(0.0, 0.0, bigRadius) | |
| } * Vector3(x, 0.0, z).xyz1 | |
| meshData[row][col] = pos.xyz | |
| } | |
| } | |
| vb.put { | |
| val textureScale = Vector2(1.0 / widthSegments, 1.0 / heightSegments) | |
| for (r in 0 until heightSegments - 1) { | |
| for (c in 0 until widthSegments - 1) { | |
| val c00 = meshData[r][c] | |
| val c01 = meshData[r + 1][c] | |
| val c10 = meshData[r][c + 1] | |
| val c11 = meshData[r + 1][c + 1] | |
| val uv00 = Vector2(c + 0.0, r + 0.0) * textureScale | |
| val uv01 = Vector2(c + 0.0, r + 1.0) * textureScale | |
| val uv10 = Vector2(c + 1.0, r + 0.0) * textureScale | |
| val uv11 = Vector2(c + 1.0, r + 1.0) * textureScale | |
| write(c11); write(uv11) | |
| write(c10); write(uv10) | |
| write(c00); write(uv00) | |
| write(c00); write(uv00) | |
| write(c01); write(uv01) | |
| write(c11); write(uv11) | |
| } | |
| } | |
| } | |
| } | |
| val composite = compose { | |
| draw { | |
| camera.applyTo(drawer) | |
| drawer.clear(ColorRGBa.WHITE) | |
| drawer.shadeStyle = shadeStyle { | |
| fragmentTransform = """ | |
| const float PI = 3.14159265359; | |
| float y = va_texCoord0.y + (1 - p_time); | |
| float waveMag = smoothstep(0.3, 0.9, va_texCoord0.y); | |
| float wave = waveMag * 0.1 * sin(10 * PI * y); | |
| float value = fract((va_texCoord0.x + wave) * 20); | |
| value = smoothstep(0.15, 0.2, abs(value - 0.5)); | |
| x_fill.rgb = vec3(value); | |
| """.trimIndent() | |
| parameter("time", time) | |
| } | |
| drawer.vertexBuffer(vb, DrawPrimitive.TRIANGLES) | |
| } | |
| post(FrameBlur()) | |
| } | |
| keyboard.keyDown.listen { | |
| if (it.name == "p") { | |
| println(Vector3.fromSpherical(camera.spherical)) | |
| println(camera.lookAt) | |
| } | |
| } | |
| val videoTarget = renderTarget(width, height, multisample = BufferMultisample.SampleCount(8)) { colorBuffer() } | |
| val resolved = colorBuffer(width, height) | |
| val videoWriter = VideoWriter.create() | |
| .size(width, height) | |
| .frameRate(60) | |
| .output("video/striped-tube.mp4") | |
| if (RECORDING) { | |
| videoWriter.start() | |
| } else { | |
| extend(OrbitalControls(camera)) | |
| //extend(GUI()) { | |
| // add(params) | |
| //} | |
| } | |
| extend { | |
| update() | |
| if (RECORDING) { | |
| drawer.isolatedWithTarget(videoTarget) { | |
| composite.draw(this) | |
| } | |
| videoTarget.colorBuffer(0).copyTo(resolved) | |
| drawer.image(resolved) | |
| if (frameCount > DELAY_FRAMES) { | |
| videoWriter.frame(resolved) | |
| } | |
| if (frameCount >= TOTAL_FRAMES * LOOPS + DELAY_FRAMES) { | |
| videoWriter.stop() | |
| application.exit() | |
| } | |
| } else { | |
| composite.draw(drawer) | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment