๐Ÿ–ผ๏ธ Artwork 02. GLSL Clouds

BamgasiJMยท์–ด์ œ

OPENRNDR

๋ชฉ๋ก ๋ณด๊ธฐ
17/17
post-thumbnail

OPENRNDR Code

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.ShadeStyle
import org.openrndr.math.Vector2
import kotlin.random.Random

data class CloudCircle(
    var position: Vector2,
    var velocity: Vector2,
    val radius: Double,
    val seed: Float
)

fun main() = application {
    configure {
        width = 800
        height = 800
    }

    program {
        // 1. ๋žœ๋ค ํฌ๊ธฐ์™€ ์œ„์น˜์˜ ์› n๊ฐœ ์ƒ์„ฑ
        val circles = List(15) {
            CloudCircle(
                position = Vector2(Random.nextDouble(100.0, 700.0), Random.nextDouble(100.0, 700.0)),
                velocity = Vector2(Random.nextDouble(-1.0, 1.0), Random.nextDouble(-1.0, 1.0)),
                radius = Random.nextDouble(40.0, 120.0),
                seed = Random.nextFloat() * 100.0f
            )
        }

        // 2. ๊ตฌ๋ฆ„ ๋…ธ์ด์ฆˆ ์…ฐ์ด๋” ์ •์˜
        val cloudStyle = ShadeStyle().apply {
            fragmentTransform = """
                vec2 st = c_boundsPosition.xy;

                // ๊ฐ„๋‹จํ•œ 2D ๋…ธ์ด์ฆˆ ํ•จ์ˆ˜
                vec2 coord = st * 4.0 + vec2(p_time * 0.2 + p_seed);
                float n = sin(coord.x) * cos(coord.y) * 0.5 + 0.5;

                // ์ค‘์‹ฌ์œผ๋กœ๋ถ€ํ„ฐ์˜ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ (์›ํ˜• ๋งˆ์Šคํ‚น ๋ฐ ํŽ˜๋”๋ง)
                float dist = length(st - vec2(0.5));
                float mask = smoothstep(0.5, 0.4, dist); // ์› ํ…Œ๋‘๋ฆฌ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ

                // ๊ตฌ๋ฆ„ ์ƒ‰์ƒ (ํฐ์ƒ‰/์—ฐํšŒ์ƒ‰ ๊ตฌ๋ฆ„๊ณผ ํ•˜๋Š˜์ƒ‰ ๋ฐฐ๊ฒฝ blend)
                vec3 cloudColor = mix(vec3(0.6, 0.7, 0.9), vec3(1.0, 1.0, 1.0), n);

                x_fill = vec4(cloudColor, mask);
            """.trimIndent()
        }

        extend {
            // ํฐ์ƒ‰ ๋ฐฐ๊ฒฝ
            drawer.clear(ColorRGBa(0.2, 0.3, 0.7))

            // ์› ์—…๋ฐ์ดํŠธ ๋ฐ ๊ทธ๋ฆฌ๊ธฐ
            for (circle in circles) {
                // 1) ์œ„์น˜ ์ด๋™ (ํ™”๋ฉด ๋ฐ–์œผ๋กœ ๋‚˜๊ฐ€๋ฉด ๋ฐ˜์‚ฌ)
                circle.position += circle.velocity
                if (circle.position.x < circle.radius || circle.position.x > width - circle.radius) {
                    circle.velocity = Vector2(-circle.velocity.x, circle.velocity.y)
                }
                if (circle.position.y < circle.radius || circle.position.y > height - circle.radius) {
                    circle.velocity = Vector2(circle.velocity.x, -circle.velocity.y)
                }

                // 2) ์…ฐ์ด๋” ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
                cloudStyle.parameter("time", seconds)
                cloudStyle.parameter("seed", circle.seed)

                // 3) ์…ฐ์ด๋” ์ ์šฉ ํ›„ ์› ๊ทธ๋ฆฌ๊ธฐ
                drawer.shadeStyle = cloudStyle
                drawer.stroke = null
                drawer.fill = ColorRGBa.WHITE
                drawer.circle(circle.position, circle.radius)
            }

            // ์…ฐ์ด๋” ์ดˆ๊ธฐํ™”
            drawer.shadeStyle = null
        }
    }
}

profile
Coding Art with Blender / Three.js / p5.js / GLSL Shader / Processing / nannou

0๊ฐœ์˜ ๋Œ“๊ธ€