Skip to content

Instantly share code, notes, and snippets.

@ricardomatias
Forked from ylegall/StripedTube.kt
Created September 15, 2021 12:07
Show Gist options
  • Save ricardomatias/b7cf2de2d8ed0f20918ac5477c1503a1 to your computer and use it in GitHub Desktop.
Save ricardomatias/b7cf2de2d8ed0f20918ac5477c1503a1 to your computer and use it in GitHub Desktop.
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