https://api.openrndr.org/index.html
์ ๋๋ ์ดํฐ๋ธ ์ฝ๋ฉ ํ๋ ์์ํฌ๋ฅผ ์ ํํ ๋ ์ ์์๋ ํํ์ ์์ ๋, ์คํ ์ฑ๋ฅ, ์์คํ ์ ์์ ์ฑ ์ฌ์ด์์ ์ ํํด์ผ ํ๋ ๋ฌธ์ ์ ์ง๋ฉดํฉ๋๋ค. p5.js, Processing, openFrameworks, Nannou ๋ฑ ๋ค์ํ ๋๊ตฌ๊ฐ ์กด์ฌํ์ง๋ง, OPENRNDR๋ Kotlin ๊ธฐ๋ฐ์ ํ๋์ ์ธ ์ค๊ณ์ GPU ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ๋ฐํ์ผ๋ก ํ๋กํ ํ์ดํ๊ณผ ์์ฉ ์ค์ผ์ผ์ ์์ฐ ๋จ๊ณ ๋ชจ๋์์ ๊ณ ์ ํ ๊ธฐ์ ์ ์ฐ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
OPENRNDR์ ์ง๊ฐ๋ ๋จ์ํ "๋ํ์ ๊ทธ๋ฆฌ๊ณ ์ ฐ์ด๋๋ฅผ ๋ถ์ธ๋ค"๋ฅผ ๋์ด, ์ค์ ์คํ๋์ค ํ๊ฒฝ ๋ฐ ๊ทธ๋ํฝ ๋์์ด๋์ ๊ฐ๊ณต ์์ ์ ํ์ํ ๋ํ ์ผ์ ์ ๊ตํ๊ฒ ์ฑ๊ฒผ๋ค๋ ์ ์ ์์ต๋๋ค.
OPENRNDR์ Drawing API๋ ๊ณ ๋ํ๋ 2D/3D ๋ฒกํฐ ๊ทธ๋ํฝ ์ฐ์ฐ๊ณผ ํ๋์จ์ด ๊ฐ์ ๋ ๋๋ง์ ์์ ํ ๊ฒฐํฉํ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ถ๊ณ ์์ต๋๋ค.
p5.js๋ Processing์ ๊ฒฝ์ฐ ๋ณต์กํ ๋ฒ ์ง์ด ๊ณก์ (Bezier Curve) ๋ถํ , ๋ฉด ๊ต์ฐจ(Boolean Operations), ์คํ์ (Offset) ๊ณ์ฐ, ํฐํธ์ ์์๋ผ์ธ ์ถ์ถ ์์ ์ ์ํํ ๋ ๋ณ๋์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์์กดํ๊ฑฐ๋ CPU ์ฐ์ฐ ๋ณ๋ชฉ์ด ๋ฐ์ํ๊ธฐ ์ฝ์ต๋๋ค.
๋ฐ๋ฉด OPENRNDR๋ ๋ด์ฅ๋ orx-shapes ๋ฐ ๋ฐฑ์๋ ์ค์ผ์ผ์ Vector Shape ์์ง์ ํตํด ๋ณต์กํ ํจ์ค ์ฐ์ฐ์ ๋ค์ดํฐ๋ธ ๋ ๋ฒจ์์ ๋์ ์ ๋ฐ๋๋ก ์ฒ๋ฆฌํฉ๋๋ค.
Shape.contours๋ฅผ ํตํด ์์์ ํด์๋๋ก ๊ณก์ ์ ์ด์ฐํํ ์ ์์ผ๋ฉฐ, ๊ฐ ์ ์ ์ ์ ยท๋ฒ์ ๋ฒกํฐ๊น์ง ์ฆ์ ์ถ์ถ ๊ฐ๋ฅํฉ๋๋ค.Shape ๊ฐ์ฒด ๊ฐ ํฉ์งํฉยท๊ต์งํฉยท์ฐจ์งํฉ์ ๋จ์ผ ํจ์ ํธ์ถ๋ก ์ํํ ์ ์์ด, ๋ก๊ณ ๋์์ธ์ด๋ ๊ธฐํํ์ ํจํด ์์ฑ์ ์ง์ ํ์ฉ๋ฉ๋๋ค.openFrameworks๋ Processing์์ FBO(Frame Buffer Object)๋ฅผ ์์ฑํ๊ณ ํ ์ค์ฒ๋ฅผ ์ด์ค ๋ฐ์ธ๋ฉํ์ฌ ๋ ๋๋ง ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถํ๋ ๊ณผ์ ์ ์ฝ๋๊ฐ ๊ธธ์ด์ง๊ณ ๋ฉ๋ชจ๋ฆฌ ๋์์ ์ํ์ด ๋ฐ๋ฆ ๋๋ค.
OPENRNDR๋ renderTarget ๊ฐ๋
์ ๊ฐ๊ฒฐํ๊ฒ ์ ์ธํ๊ณ , ๋ฐ์ธ๋ฉ ๋ฐ ์ปจํ
์คํธ ์ ํ์ ํจ์ํ ๋ธ๋ก(draw {}) ๋ด์์ ์์ ํ๊ฒ ๊ฒฉ๋ฆฌํฉ๋๋ค.
val offscreen = renderTarget(width, height) {
colorBuffer(0)
depthBuffer()
}
offscreen.draw {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = ColorRGBa.WHITE
drawer.circle(width / 2.0, height / 2.0, 150.0)
}
// ๋ฉ์ธ ์บ๋ฒ์ค์ ์คํ์คํฌ๋ฆฐ ๊ฒฐ๊ณผ๋ฅผ ํฉ์ฑ
drawer.image(offscreen.colorBuffer(0))
์ด๋ฅผ ํตํด ๋ณต์กํ ๋ฉํฐ ํจ์ค ๋ ๋๋ง ์์คํ
์ ์์ฑํ ๋ ๋ฐ์ํ ์ ์๋ OpenGL ์ํ ์ค์ผ์ ๋ฐฉ์งํ๊ณ , ๋ฆฌ์์ค ํด์ (destroy()) ์์ ๋ ๋ช
ํํ๊ฒ ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
| ํ๋ ์์ํฌ | ๋ ๋๋ง ๋ฐฑ์๋ | ํ๊ณ์ |
|---|---|---|
| openFrameworks (C++) | OpenGL / Vulkan | ์ฐ์ํ ์ฑ๋ฅ์ด๋ ๋น๋ ์๋ ๋๋ฆผ, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ๊น๋ค๋ก์ |
| p5.js (JavaScript) | WebGL (๋ธ๋ผ์ฐ์ ) | ์ฑ๊ธ ์ค๋ ๋ ํ๊ณ, ์๋ง ๊ฐ ๋ฒกํฐ ๋ฐ์ดํฐ ์ค์๊ฐ ์ฒ๋ฆฌ ๊ณค๋ |
| OPENRNDR (Kotlin/JVM) | LWJGL โ OpenGL 3.3+ | C++์ ์ก๋ฐํ๋ ์ฑ๋ฅ + ์ฆ๊ฐ์ ์ธ ์ปดํ์ผ ํ๊ฒฝ ๋์ ํ๋ณด |
OPENRNDR๋ JVM ์์์ LWJGL(Lightweight Java Game Library)์ ํตํด OpenGL 3.3+์ ์ง์ ์ ๊ทผํ๋ฏ๋ก, ๋ณต์กํ ํํฐํด ์์คํ ์ด๋ ๋๊ท๋ชจ ๋ฒกํฐ ์ฐ์ฐ์์๋ ์์ ์ ์ธ ํ๋ ์ ๋ ์ดํธ๋ฅผ ์ ์งํฉ๋๋ค.
OPENRNDR๋ ๋จ์ํ GLSL ์ฝ๋๋ฅผ ํ ์ค์ฒ ํจ์ค ํํ๋ก ๋ก๋ํ๋ ์์ค์ ๋์ด, ์ ฐ์ด๋ ์ฝ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ํ๋ฅผ ์ ๊ธฐ์ ์ผ๋ก ์ฐ๊ฒฐํ๋ ์์คํ ์ ๊ฐ์ถ๊ณ ์์ต๋๋ค.
๊ธฐ์กด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ปค์คํ GLSL ์ ฐ์ด๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ฒํ ์ค ์ ฐ์ด๋์ ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋์ ์ ์ฒด ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ฝ๋๋ฅผ ์ง์ ์์ฑํด์ผ ํฉ๋๋ค.
OPENRNDR์ ShadeStyle์ ํ์ดํ๋ผ์ธ ๋ด๋ถ์ ํน์ ๋จ๊ณ(Vertex Transform, Fragment Color ๋ฑ)์๋ง ์ฌ์ฉ์๊ฐ ์์ฑํ GLSL ์กฐ๊ฐ์ ์ฃผ์
(inject) ํ๋ ๋ฐฉ์์ ์ทจํฉ๋๋ค.
// ๊ธฐ๋ณธ 2D ๋ํ Drawing API ์์ GLSL ํ๋๊ทธ๋จผํธ ๋ก์ง์ ์ง์ ์ฃผ์
drawer.shadeStyle = shadeStyle {
fragmentPreamble = """
float noise(vec2 st) {
return fract(sin(dot(st, vec2(12.9898, 78.233))) * 43758.5453123);
}
"""
fragmentTransform = """
vec2 st = c_boundsPosition.xy;
x_fill.rgb *= noise(st * p_scale + p_time);
"""
parameter("scale", 10.0)
parameter("time", seconds)
}
drawer.rectangle(100.0, 100.0, 400.0, 400.0)
์ด ๊ตฌ์กฐ์ ํต์ฌ ์ด์ :
vertexTransform, fragmentTransform, fragmentPreamble ๋ฑ ์ธ๋ถํ๋ ์ฃผ์
ํฌ์ธํธ ์ ๊ณตKotlin ์ฝ๋์์ parameter("name", value) ํํ๋ก ์ ์ธ๋ ๋ณ์๋ GLSL ์
ฐ์ด๋ ๋ด์ p_name ๋ณ์๋ก ์๋ ๋งคํ๋ฉ๋๋ค.
parameter("scale", 10.0) // GLSL: uniform float p_scale;
parameter("offset", Vector2(1.0, 2.0)) // GLSL: uniform vec2 p_offset;
parameter("tint", ColorRGBa.PINK) // GLSL: uniform vec4 p_tint;
parameter("tex", colorBuffer) // GLSL: uniform sampler2D p_tex;
Float, Vector, Color, Matrix, BufferImage(Texture) ๋ฑ ๋ค์ํ ๋ฐ์ดํฐ ํ์
์ด OpenGL Uniform ์ ๋ฌ ๊ณผ์ ์ ์๋ ๋ฐ์ธ๋ฉ ์ฝ๋ ์์ด ์ฆ์ ๋๊ธฐํ๋ฉ๋๋ค. ์ด๋ openFrameworks์์ shader.setUniform1f(...), shader.setUniform2f(...) ๋ฑ์ ์ผ์ผ์ด ํธ์ถํด์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ ์์ ํ ์ ๊ฑฐํฉ๋๋ค.
์ ๋๋ ์ดํฐ๋ธ ์ํธ ์์ ์:
OPENRNDR๋ ์ด ๋ ์์ญ์ ๊ฒฝ๊ณ๋ฅผ ์์ค ํ์ด๋ธ๋ฆฌ๋ ์ํฌํ๋ก์ฐ๋ฅผ ์ง์ํฉ๋๋ค.
Shape ๊ตฌ์กฐ์ฒด๋ก ์์ฑํ ์ํ์ ๋ฒ ์ง์ด ํจ์ค ๋ฐ์ดํฐ๋ฅผ GPU ๋ฒํผ๋ก ๋ณด๋ธ ๋ค, ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋์์ SDF(Signed Distance Field) ๊ธฐ์ ๊ณผ ๊ฒฐํฉํ์ฌ ์ค์๊ฐ ํํฐ ๋ฐ ๋ณํ ํจ๊ณผ๋ฅผ ๋ถ์ฌํ ์ ์์ต๋๋ค.
[CPU: Shape/Contour ์์ฑ] โ [GPU Buffer ์
๋ก๋] โ [Fragment Shader: SDF ๋ ๋๋ง + ๋ณํ]
orx-fx ๋ชจ๋์ ์ฌ์ฉํ๋ฉด Drawing API๋ก ๊ทธ๋ ค์ง ์บ๋ฒ์ค์ GLSL ๊ธฐ๋ฐ ๋ธ๋ฌ, ๊ธ๋ก์ฐ, ํผ๋๋ฐฑ ๋
ธ์ด์ฆ ํจ๊ณผ๋ฅผ ๋ฉ์๋ ์ฒด์ด๋ ํํ๋ก ์กฐํฉํ ์ ์์ต๋๋ค.
val post = Post(window)
post.add(ApproximateGaussianBlur()).apply {
window = 5
gain.set(1.0, 1.0)
}
post.add(ChromaticAberration())
post.add(FilmGrain())
extend(post)
| ์ญํ | ๋ด๋น ๊ณ์ธต |
|---|---|
| ์ขํ๊ณ, ๋งคํธ๋ฆญ์ค ์ฐ์ฐ, ๋ํ ๋ฐฐ์น | Drawing API ๋ช ๋ น์ด |
| ๋ด๋ถ ์ง๊ฐ, ์ปฌ๋ฌ ํ๋, ํ์ ๋จ์ ์ฐ์ฐ | GLSL ์ ฐ์ด๋ |
์ด ๋ถ๋ฆฌ ๊ตฌ์กฐ ๋๋ถ์ ๊ทธ๋ํฝ ์ ์ด ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ฑ๋ฅ์ ๋์์ ์ ์งํ ์ ์์ต๋๋ค.
openFrameworks, Processing, p5.js, Nannou ๋ฑ ํ ํ๋ ์์ํฌ์ ๋น๊ตํ์ ๋ OPENRNDR๊ฐ ์ฐ์์ ์๋ ํต์ฌ ์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
OPENRNDR๋ ์ฝ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋งค์ฐ ๊ฐ๋ณ๊ฒ ์ ์งํ๋ ๋์ , ORX๋ผ๋ ๊ณต์ ํ์ฅ ํ๋ฌ๊ทธ์ธ ์ํ๊ณ๋ฅผ ํตํด ์ ๋๋ ์ดํฐ๋ธ ์ํธ์ ํ์ํ ๊ณ ๊ธ ๊ธฐ๋ฅ๋ค์ ๋ชจ๋์์ผ๋ก ์ ๊ณตํฉ๋๋ค.
orx-gui โ ์๋ UI ์์ฑ์ฝ๋ ๋ด์ ๋ณ์์ @DoubleParameter ๊ฐ์ ์ด๋
ธํ
์ด์
๋ง ๋ถ์ด๋ฉด, ํ๋ก๊ทธ๋จ ์คํ ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐ์ ํ ์ ์๋ ์ฌ๋ผ์ด๋ยท์ปฌ๋ฌํฝ์ปค GUI ์ฐฝ์ด ์๋์ผ๋ก ์์ฑ๋ฉ๋๋ค.
class Settings {
@DoubleParameter("Scale", 0.1, 20.0)
var scale: Double = 5.0
@ColorParameter("Base Color")
var baseColor: ColorRGBa = ColorRGBa.PINK
@DoubleParameter("Speed", 0.0, 3.0)
var speed: Double = 1.0
}
p5.js์์ dat.GUI๋ quicksettings๋ฅผ ๋ณ๋๋ก ์ํฌํธยท์ฐ๊ฒฐํ๊ฑฐ๋, C++์์ ofxGui๋ฅผ ์๋ ๋ฐฐ์นํด์ผ ํ๋ ๋ฒ๊ฑฐ๋ก์์ด ์ ํ ์์ต๋๋ค.
orx-fx โ ํฌ์คํธ ํ๋ก์ธ์ฑ ํํฐ๋ธ๋ฌ, ๋์คํ ์ , ๋ธ๋ฃธ, ํฌ๋ก๋งคํฑ ์๋ฒ ๋ ์ด์ (์์์ฐจ), ํผํํธ๋ก , ํผ๋๋ฐฑ ๋ฒํผ ๋ฑ ์์ญ ๊ฐ์ง ๊ทธ๋ํฝ ํํฐ๋ฅผ ๋จ ํ ์ค์ ์ฝ๋๋ก ์ฒด์ด๋ํ ์ ์์ต๋๋ค. ๊ฐ ํํฐ๋ ๋ด๋ถ์ ์ผ๋ก ์ต์ ํ๋ GLSL ํจ์ค๋ก ๊ตฌํ๋์ด ์์ด, ๋ณต์กํ ์ ฐ์ด๋ ์ฝ๋๋ฅผ ์ง์ ์์ฑํ์ง ์์๋ ํ๋ก๋์ ํ์ง์ ๋น์ฃผ์ผ์ ๋น ๋ฅด๊ฒ ์กฐํฉํ ์ ์์ต๋๋ค.
orx-camera / orx-marching-cubes๋๋ถ๋ถ์ ํฌ๋ฆฌ์์ดํฐ๋ธ ์ฝ๋ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ RGB ๋๋ HSB/HSL ์์ ๊ณต๊ฐ๋ง ์ง์ํฉ๋๋ค.
๋ฐ๋ฉด OPENRNDR๋ ๋์์ด๋ ์๊ฐ ์ค์ฌ์ ์์ ๊ณต๊ฐ์ ๊ธฐ๋ณธ ํ์
์ผ๋ก ํ์ฌํ๊ณ ์์ต๋๋ค.
| ์ง์ ์์ ๊ณต๊ฐ | ์ฉ๋ |
|---|---|
ColorRGBa | ํ์ค sRGB ์ถ๋ ฅ |
ColorHSVa | ์ง๊ด์ ์์ ์ ํ |
ColorXSVa | ํ์ฅ๋ HSV ๋ณํ |
ColorLABa (CIE Lab) | ์ง๊ฐ ๊ท ๋ฑ ๋ณด๊ฐ |
ColorOKLaba / ColorOKLCHa | ์ต์ OKLab/OKLCH โ ๊ฐ์ฅ ์์ฐ์ค๋ฌ์ด ๊ทธ๋ผ๋ฐ์ด์ |
ColorXYZa | CIE XYZ ์์ญ ๊ด๋ฆฌ |
RGB ๊ณต๊ฐ์์ ํ๋(#0000FF)๊ณผ ๋
ธ๋(#FFFF00)์ ์ ํ ๋ณด๊ฐํ๋ฉด ์ค๊ฐ์ ํํ ํ์์ด ๋ฑ์ฅํฉ๋๋ค. ๊ทธ๋ฌ๋ OKLab/LCH ๊ณต๊ฐ์์ ๋์ผ ๋ณด๊ฐ์ ์ํํ๋ฉด ์ฑ๋๊ฐ ์ ์ง๋ ์์ฐ์ค๋ฝ๊ณ ์ ๊ธฐ์ ์ธ ๊ทธ๋ผ๋ฐ์ด์
์ ์ป์ ์ ์์ต๋๋ค.
val c1 = ColorOKLCHa(0.7, 0.15, 240.0) // ํ๋ ๊ณ์ด
val c2 = ColorOKLCHa(0.7, 0.15, 90.0) // ๋
ธ๋ ๊ณ์ด
val gradient = mix(c1, c2, t) // ์์ฐ์ค๋ฌ์ด ์์ ์ ์ด
๋ธ๋๋ฉ ์ํธ์ํฌ, ๊ทธ๋ํฝ ํฌ์คํฐ, ์ธ์ ๋งค์ฒด ์ฐ๊ณ ์์ ์ ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ฐจ๋ณํ๋๋ ๊ฐ๊ฐ์ ์ธ ์๊ฐ์ ํํํ ์ ์์ผ๋ฉฐ, Pantone ๋๋ ํน์ ๋ธ๋๋ ์ปฌ๋ฌ์์ ์ ํฉ์ฑ ๊ด๋ฆฌ์๋ ์ ๋ฆฌํฉ๋๋ค.
Processing์ด๋ p5.js๋ ๊ธ์๋ฅผ ์ด๋ฏธ์ง ํฝ์
์ ๋๋ก๋ง ๋ค๋ฃจ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค.
OPENRNDR๋ ํฐํธ๋ฅผ ๋ฒกํฐ ์ปจํฌ์ด(Vector Outline)๋ก ์ง์ ๋ถํดํ ์ ์์ต๋๋ค.
val writer = FontImageMap.fromUrl("data/fonts/Inter-Bold.ttf", 120.0)
val textShape = writer.shapesFor("OPENRNDR")
textShape.forEach { shape ->
shape.contours.forEach { contour ->
contour.equidistantPositions(64).forEachIndexed { i, pt ->
// ๊ฐ ์ ์ ํํฐํด ๋ฐฐ์น, ์ํ์ ์๊ณก ์ ์ฉ ๋ฑ
drawer.circle(pt + Vector2(sin(i * 0.3) * 10.0, 0.0), 2.0)
}
}
}
Shape๋ก ํ์ฉํ์ฌ ํด๋ฆฌํ ๋ง์คํฌ ๋๋ ํจํด ์ฑ์ฐ๊ธฐloadSVG()๋ก ํ์ผ์ ๋ถ๋ฌ์ ๋ ์ด์ด๋ณ Shape ๋ฐ์ดํฐ๋ก ๋ถํดContour์ ์ ์ด์ ์ ์์ , ์ค๋ฌด๋ฉ, ์๋ธ๋๋น์ saveSVG() / PDF ํฌ๋งท์ผ๋ก ์ถ๋ ฅ์ด ํ์ดํ๋ผ์ธ์ ์ธ์์ฉ ํฌ์คํฐ, ๋ ์ด์ ์ปคํ ๋ฐ์ดํฐ, CNC ๊ฐ๊ณต ๊ฒฝ๋ก ์์ฑ ๋ฑ ๋ฌผ๋ฆฌ์ ์ถ๋ ฅ ์ํฌํ๋ก์ฐ์ ์ง์ ์ฐ๊ฒฐ๋ฉ๋๋ค.
C++(openFrameworks)๋ณด๋ค ํจ์ฌ ์์ ํ๊ณ ๋น ๋ฅด๊ฒ ๊ฐ๋ฐํ ์ ์์ผ๋ฉด๋ฉด์, Java/JS๋ณด๋ค ๋ฌธ๋ฒ์ด ๊ฐ๊ฒฐํฉ๋๋ค.
drawer.isolated { ... } ๊ฐ์ ๋ธ๋ก ๊ตฌ๋ฌธ ๋๋ถ์ ๊ทธ๋ํฝ ๋ณํ Matrix(Translate, Rotate, Scale)์ ์ค์ฝํ๋ฅผ pushMatrix/popMatrixํ ํ์ ์์ด ์ง๊ด์ ์ผ๋ก ๊ฒฉ๋ฆฌํ ์ ์์ต๋๋ค.
drawer.isolated {
drawer.translate(width / 2.0, height / 2.0)
drawer.rotate(45.0)
drawer.fill = ColorRGBa.RED
drawer.rectangle(-50.0, -50.0, 100.0, 100.0)
}
// ๋ธ๋ก ์ข
๋ฃ ํ ๋ชจ๋ ๋ณํ ์ํ๊ฐ ์๋์ผ๋ก ๋ณต์๋จ
์ฝํ๋ฆฐ์ ํ์ ์์คํ ๋๋ถ์ ๋ฐํ์ ํฌ๋์๊ฐ ๋ํญ ์ค์ด๋ค๊ณ , ์ํ ๋ฐ ๋ฒกํฐ ์ฐ์ฐ ํํ์์ด ๋งค์ฐ ๊น๋ํ๊ฒ ์์ฑ๋ฉ๋๋ค.
val position = Vector2(10.0, 20.0)
val velocity = Vector2(1.5, 0.8)
val newPosition = position + velocity * 2.0 // ์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ
// Null Safety: ์ปดํ์ผ ์์ ์ ๋ ๊ฐ๋ฅ์ฑ ์ฐจ๋จ
val config: Settings? = loadConfig()
config?.let { applySettings(it) } // NullPointerException ์์ฒ ๋ฐฉ์ง
data class Particle(
val position: Vector2,
val velocity: Vector2,
val color: ColorRGBa
)
val moved = particle.copy(position = particle.position + particle.velocity)
data class์ copy() ๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ๊ฐ์ฒด์ ๋ณต์ฌ ๋ฐ ๋ณํ ์ฐ์ฐ์ ์์ ํ๊ฒ ์ํํ ์ ์์ผ๋ฉฐ, ๋ถ๋ณ ๊ฐ์ฒด ์ค์ฌ์ ์ค๊ณ๋ก ๋ณต์กํ ํํฐํด ์์คํ
์ด๋ ์์น ์ฐ์ฐ ์ ์ํ ๋ณ๊ฒฝ ์ค๋ฅ๋ฅผ ์์ฒ์ ์ผ๋ก ๋ฐฉ์งํฉ๋๋ค.
๋ฏธ๋์ด ์ํธ ์ ์๋ ์์ ๊ทธ๋ํฝ ์์ ์ ํ์์ ์ธ ์ถ๋ ฅ ์์คํ ์ ์ ๊ณตํฉ๋๋ค.
| ์ถ๋ ฅ ํฌ๋งท | ์ฉ๋ |
|---|---|
| PNG / TIFF | ๊ณ ํด์๋ ์ ์ง ์ด๋ฏธ์ง (์ธ์, ํฌํธํด๋ฆฌ์ค) |
| SVG | ๋ฒกํฐ ํ์ผ (๋ ์ด์ ์ปคํ , ์ธ์ ๋งค์ฒด) |
| H.264 (MP4) | ์น ๊ณต์ ์ฉ ๋์์ |
| ProRes 422 / 4444 | ๋ฐฉ์กยท์ ์์ฉ ๊ณ ํ์ง ๋์์ |
| EXR ์ํ์ค | HDR ํฉ์ฑ์ฉ ํ๋ ์ ์ํ์ค |
// ํ ์ค๋ก ๊ณ ํด์๋ ์คํฌ๋ฆฐ์ท
extend(Screenshots())
// ํ๋ ์ ๋๋ ์๋ ๋์์ ๋
นํ
extend(VideoWriter()).apply {
codec = "h264"
bitrate = 20_000_000
output = "output.mp4"
}
์ปดํจํฐ ํ๋ ์ ๋ ์ดํธ๊ฐ ์๊ฐ์ ์ผ๋ก ๋จ์ด์ง๋๋ผ๋, ์๊ฐ ์ถ์ ๊ณ ์ ํ ์ฑ ์ ํํ FPS๋ก ๋ ๋๋ง ๋์์์ ์ถ์ถํ ์ ์์ต๋๋ค.
extend(VideoWriter()).apply {
realTime = false // ์คํ๋ผ์ธ ๋ชจ๋: ํ๋ ์ ๋๋ ๋ฌด์
frameRate = 60.0
}
์ด ๊ธฐ๋ฅ์ ๋ณต์กํ ์๋ฎฌ๋ ์ด์ ์ด๋ ๊ณ ๋ถํ ์ ฐ์ด๋ ์์ ์์๋ ์๋ฒฝํ ๋งค๋๋ฌ์ด ์ต์ข ๊ฒฐ๊ณผ๋ฌผ์ ๋ณด์ฅํฉ๋๋ค.
OPENRNDR์ API ๋์์ธ์ Kotlin์ ์ธ์ด์ ํน์ฑ์ ์ ๊ทน ํ์ฉํ๋๋ก ์ค๊ณ๋์ด ์์ต๋๋ค.
| Kotlin ํน์ง | OPENRNDR์์์ ํ์ฉ |
|---|---|
| ์์ ๊ฐ์ฒด ์ง์ ๋๋ค | drawer.isolated { }, renderTarget.draw { } ๋ฑ ์ปจํ
์คํธ ๊ฒฉ๋ฆฌ |
| ํ์ฅ ํจ์ | Vector2.rotate90() ๋ฑ ๊ธฐ์กด ํ์
์ ๋ฉ์๋ ์ถ๊ฐ |
๋ ์์ ์ฑ (Type?) | ๋ฆฌ์์ค ๋ฏธ์ด๊ธฐํยท๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์ค๋ฅ ์ปดํ์ผ ํ์ ์ฐจ๋จ |
| ์ฐ์ฐ์ ์ค๋ฒ๋ก๋ฉ | position + velocity * 2.0 ๋ฑ ์ง๊ด์ ๋ฒกํฐยท์์ ์ฐ์ฐ |
| ๋ฐ์ดํฐ ํด๋์ค / ๋ถ๋ณ์ฑ | ํํฐํดยท์ํ ๊ฐ์ฒด์ ์์ ํ ๋ณต์ฌยท๋ณํ |
| ๋น๊ต ๋์ | OPENRNDR๊ฐ ๋ฐ์ด๋ ์ |
|---|---|
| vs p5.js / Processing | JVM ๊ธฐ๋ฐ์ ์๋์ ์ธ ์ฑ๋ฅ, ๊ณ ๊ธ ์์ํ(OKLab/OKLCH), ์๋ GUI ์์ฑ(orx-gui), ํ๋์ Kotlin DSL ๋ฌธ๋ฒ, ์ ๋ฐ ๋ฒกํฐ ์ฐ์ฐ |
| vs openFrameworks (C++) | CMake/C++ ์ปดํ์ผ ์คํธ๋ ์ค ์์, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์์ ์ฑ(๊ฐ๋น์ง ์ปฌ๋ ์ ), ๋น ๋ฅด๊ฒ ๋ถ์ผ ์ ์๋ UIยทํํฐ ์ฒด์ธ, ์ ฐ์ด๋ ๋ณด์ผ๋ฌํ๋ ์ดํธ ์ต์ํ |
| vs Nannou (Rust) | ์ง์ ์ฅ๋ฒฝ์ด ๋ฎ์(Kotlin ํ์ต ๊ณก์ ์๋ง), ํฌ์คํธ ํ๋ก์ธ์ฑ ๋ฐ ํ์ดํฌ๊ทธ๋ํผ/SVG ๋ฒกํฐ ๊ฐ๊ณต ํด์ ์ด ๋ ํ๋ถ, ORX ์ํ๊ณ์ ์ฑ์๋ |
OPENRNDR๋ ํ๋กํ ํ์ดํ ๋๊ตฌ์ธ Processing๊ณผ, ์ค์ ๋ฐ ๋น๋ ํ๊ฒฝ์ด ๋ณต์กํ openFrameworks ์ฌ์ด์์ ๊ธฐ์ ์ ๊ท ํ์ ์ด๋ฃจ๋ ํ๋ ์์ํฌ์ ๋๋ค.
์ด ๋ชจ๋ ์์๋ฅผ ํ๋์ ํ๋ ์์ํฌ์์ ํตํฉ ์ ๊ณตํ์ฌ, ์ ๋ฌธ์ ์ธ ์ ๋๋ ์ดํฐ๋ธ ์ํธ ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ตฌ์ฑํฉ๋๋ค.