๐Ÿ”ฎ :: Flower Dance

BamgasiJMยท2025๋…„ 9์›” 28์ผ

Nannou <Generative Art>

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

  • ์ฐฝ ํฌ๊ธฐ์— ๋งž์ถฐ ๋ฐ˜์ง€๋ฆ„/์  ํฌ๊ธฐ๋ฅผ ์Šค์ผ€์ผ๋ง
  • ์—ฌ๋Ÿฌ ๋ ˆ์ด์–ด(๋ง)๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ์†๋„/์ง„ํญ์œผ๋กœ ์›€์ง์ด๊ฒŒ ํ•˜์—ฌ ๋‹ค์ด๋‚ด๋ฏนํ•œ ํšจ๊ณผ
  • ๊ฐ ์ ์€ ์ž‘๊ฒŒ(w_h ๊ธฐ์ค€) ๊ทธ๋ฆฌ๊ณ  ์‹œ๊ฐ„์— ๋”ฐ๋ผ ํฌ๊ธฐ/์ƒ‰์ด ๋ณ€ํ•จ

๐Ÿ“ Rust Code

use nannou::prelude::*;

fn main() {
    nannou::app(model)
        // ์ดˆ๊ธฐ ์ฐฝ ํฌ๊ธฐ (resizable = true ๋กœ ์ฐฝ ํฌ๊ธฐ ๋ณ€๊ฒฝ ์‹œ์—๋„ ์ž๋™ ๋ฐ˜์‘)
        .update(update)
        .simple_window(view)
        .run();
}

struct Model {
    t: f32, // ๋‹จ์ˆœ ์‹œ๊ฐ„ ๋ˆ„์  ๋ณ€์ˆ˜ (์• ๋‹ˆ๋ฉ”์ด์…˜ ์šฉ)
}

fn model(_app: &App) -> Model {
    Model { t: 0.0 }
}

// update: ํ”„๋ ˆ์ž„๋งˆ๋‹ค ํ˜ธ์ถœ๋˜์–ด ์‹œ๊ฐ„ ๋ณ€์ˆ˜๋ฅผ ์ฆ๊ฐ€์‹œํ‚ด
fn update(_app: &App, model: &mut Model, _update: Update) {
    // ์‹œ๊ฐ„ ์ฆ๋ถ„๊ฐ’: ์ด ๊ฐ’์„ ํ‚ค์šฐ๋ฉด ์ „์ฒด ์• ๋‹ˆ๋ฉ”์ด์…˜ ์†๋„๊ฐ€ ๋นจ๋ผ์ง
    model.t += 0.015;
}

// view: ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ํ™”๋ฉด์„ ๊ทธ๋ฆผ
fn view(app: &App, model: &Model, frame: Frame) {
    let draw = app.draw();

    // ๋ฐฐ๊ฒฝ
    draw.background().color(hsla(0.0, 0.0, 0.01, 1.0));

    // window_rect()๋Š” ํ˜„์žฌ ์ฐฝ์˜ ์ขŒํ‘œ๊ณ„๋ฅผ ๋ฆฌํ„ด (๋งค ํ”„๋ ˆ์ž„ ๊ฐฑ์‹ ๋จ)
    // - ์ขŒํ‘œ ์ค‘์‹ฌ์€ (0,0), ์ขŒ/์šฐ/์ƒ/ํ•˜ ๊ฒฝ๊ณ„๋Š” win.left(), win.right(), win.top(), win.bottom()
    let win = app.window_rect();
    // ์œˆ๋„์šฐ์˜ ์งง์€ ์ชฝ์„ ๊ธฐ์ค€์œผ๋กœ ์Šค์ผ€์ผ์„ ๋งž์ถ”๋ฉด ํ™”๋ฉด ๋น„์œจ์— ๊ด€๊ณ„์—†์ด ๋ณด๊ธฐ ์ข‹์Œ
    let min_dim = win.w().min(win.h());

    // ๋ ˆ์ด์–ด(๋ง) ์ˆ˜: ์ˆซ์ž๋ฅผ ๋ฐ”๊พธ๋ฉด ๋ณต์žก๋„/๋ฐ€๋„๊ฐ€ ๋ณ€ํ•จ
    let layers = 30;
    for i in 0..layers {
        let fi = i as f32;
        let layer_frac = fi / (layers as f32); // 0..1 ๋น„์œจ

        // ๊ฐ ๋ ˆ์ด์–ด์˜ ๊ธฐ์ค€ ๋ฐ˜์ง€๋ฆ„: ์œˆ๋„์šฐ ํฌ๊ธฐ์— ๋น„๋ก€
        // ๋‚ด๋ถ€ ๋ ˆ์ด์–ด๋Š” ์ž‘๊ณ  ๋ฐ”๊นฅ ๋ ˆ์ด์–ด๋Š” ํผ
        let base_r = min_dim * (0.08 + layer_frac * 0.32);

        // ํšŒ์ „ ์†๋„, ์ง„๋™(wobble) ๋“ฑ ๋ ˆ์ด์–ด๋งˆ๋‹ค ๋‹ค๋ฅด๊ฒŒ ์คŒ
        let rot_speed = 0.3 + layer_frac * 0.9;         // ํšŒ์ „ ์†๋„
        let wobble = 6.0 + layer_frac * 22.0;           // ๋ฐ˜์ง€๋ฆ„ ์ง„๋™ ํญ

        // ์ƒ‰์ƒ: ๋ ˆ์ด์–ด๋งˆ๋‹ค ๊ธฐ๋ณธ hue๊ฐ€ ๋‹ค๋ฅด๊ณ , ์‹œ๊ฐ„์ด ์ง€๋‚˜๋ฉด์„œ ์ฒœ์ฒœํžˆ ๋ณ€ํ™”
        // hue๋ฅผ 0..1๋กœ ๋งŒ๋“ค๊ณ  ์‚ฌ์ธ์œผ๋กœ rgb๋ฅผ ๋งŒ๋“ค์–ด ์•ฝ๊ฐ„ ํŒŒ์Šคํ…”ํ†ค ๋А๋‚Œ
        let hue = (layer_frac + model.t * 0.03).fract();
        let phase = hue * TAU;
        let r = 0.55 + 0.45 * (phase).sin();
        let g = 0.40 + 0.60 * (phase + 2.0).sin();
        let b = 0.50 + 0.50 * (phase + 4.0).sin();
        let alpha = 0.85 - layer_frac * 0.65; // ์•ˆ์ชฝ์€ ํˆฌ๋ช…๋„ ๋†’๊ณ  ๋ฐ”๊นฅ์€ ๋‚ฎ๊ฒŒ

        // ์ด ๋ ˆ์ด์–ด์˜ ์  ๊ฐœ์ˆ˜: ์•ˆ์ชฝ์€ ์ ๊ณ  ๋ฐ”๊นฅ์ชฝ์€ ๋งŽ๊ฒŒ
        let points = 18 + i * 10;

        // ๋ ˆ์ด์–ด ํšŒ์ „ ์˜คํ”„์…‹ (์ง์ˆ˜/ํ™€์ˆ˜ ๋ ˆ์ด์–ด ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „)
        let layer_rot = model.t * rot_speed * if i % 2 == 0 { 1.0 } else { -1.0 };

        for j in 0..points {
            let fj = j as f32;

            // ๊ฐ ์ ์˜ ๊ฐ๋„: ์ธ๋ฑ์Šค์— ๋”ฐ๋ผ ์›์ฃผ์— ๊ท ๋“ฑ ๋ถ„ํฌ์‹œํ‚ค๊ณ  ๋ ˆ์ด์–ด ํšŒ์ „ ๋”ํ•จ
            let angle = map_range(fj, 0.0, (points - 1) as f32, 0.0, TAU) + layer_rot;

            // ๋ฐ˜์ง€๋ฆ„ ๊ณ„์‚ฐ: ๊ธฐ๋ณธ ๋ฐ˜์ง€๋ฆ„(base_r)์— ์—ฌ๋Ÿฌ ์ฃผ๊ธฐ์˜ ์‚ฌ์ธํŒŒ๋ฅผ ๊ฒน์ณ ์„ธ๋ฐ€ํ•œ ์ง„๋™(๋…ธ์ด์ฆˆ ๋น„์Šทํ•œ)์„ ๋งŒ๋“ฆ
            let r_noise = (model.t * (0.8 + fi * 0.6) + fj * 0.35).sin() * 0.6
                          + (model.t * (1.5 + fi * 0.4) - fj * 0.12).sin() * 0.3;
            let r_final = base_r + r_noise * wobble;

            // ๊ทน์ขŒํ‘œ -> ์ง๊ต ์ขŒํ‘œ ๋ณ€ํ™˜
            let x = r_final * angle.cos();
            let y = r_final * angle.sin();

            // ์  ํฌ๊ธฐ: ์œˆ๋„์šฐ ํฌ๊ธฐ์— ๋น„๋ก€(์ž‘๊ฒŒ), ์‹œ๊ฐ„์— ๋”ฐ๋ผ ์•ฝ๊ฐ„ ๋ณ€๋™
            let base_dot = min_dim * 0.008; // ์œˆ๋„์šฐ ํฌ๊ธฐ์— ๋น„๋ก€ํ•œ ๊ธฐ๋ณธ ์  ํฌ๊ธฐ (์ž‘๊ฒŒ ์„ค์ •)
            let dot = (base_dot * (0.6 + 0.8 * (model.t * 2.0 + fi * 0.3 + fj * 0.07).sin())).max(1.0);

            // ๊ทธ๋ฆฌ๊ธฐ: pt2()๋กœ ์ขŒํ‘œ๋ฅผ ๋งŒ๋“ค๊ณ  .xy(...)๋ฅผ ์‚ฌ์šฉ
            draw.ellipse()
                .xy(pt2(x, y))
                .w_h(dot, dot)
                .rgba(r, g, b, alpha * 0.9);
        }
    }

    // ํ˜„์žฌ ๊ทธ๋ฆฐ ๋‚ด์šฉ์„ ํ™”๋ฉด์— ๋ฐ˜์˜
    draw.to_frame(app, &frame).unwrap();
}

profile
Coding Art with Blender / oF / Processing / p5.js / nannou

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