

w_h ๊ธฐ์ค) ๊ทธ๋ฆฌ๊ณ ์๊ฐ์ ๋ฐ๋ผ ํฌ๊ธฐ/์์ด ๋ณํจ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();
}