Rendering - kuimoani/defold GitHub Wiki

Rendering

์—”์ง„์— ์˜ํ•ด ํ™”๋ฉด์— ๋‚˜ํƒ€๋‚˜๋Š” ๋ชจ๋“  ์˜ค๋ธŒ์ ํŠธ(sprites, models, tiles, particles, GUI nodes)๋Š” ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ์— ์˜ํ•ด ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ์ด ๋ฉ”๋‰ด์–ผ์€ ํŒŒ์ดํ”„ ๋ผ์ธ์ด ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋ฉฐ ์ด๊ฒƒ์„ ์–ด๋–ป๊ฒŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•˜๋ฉด ๋˜๋Š”์ง€ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ Defold๋Š” ๋ชจ๋“  2D ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํŠน์ • ๋ธ”๋ Œ๋”ฉ๊ณผ ์ ๋‹นํ•œ Z depth๋กœ ์ ์ ˆํ•˜๊ฒŒ ๋น„ํŠธ๋งต์„ ๊ทธ๋ ค์ฃผ๋ฏ€๋กœ ์ •๋ ฌ(ordering)๊ณผ ๋ธ”๋ Œ๋”ฉ(blending) ์ด์ƒ์˜ ๋ Œ๋”๋ง์— ๋Œ€ํ•˜์—ฌ ๊ณ ๋ฏผํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์ด ํŒŒ์ดํ”„๋ผ์ธ์€ ๋Œ€๋ถ€๋ถ„์˜ 2D ๊ฒŒ์ž„์—์„œ ์ž˜ ๋™์ž‘ํ•˜์ง€๋งŒ, ๋˜ ๋‹ค๋ฅธ ํŠน๋ณ„ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ด ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Defold์—์„œ๋Š” ์ด๋Ÿฐ ๊ฒฝ์šฐ์— ๋งž์ถคํ˜• ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

The default renderer

๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ์˜ ํ•ต์‹ฌ์€ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ(render script)์ž…๋‹ˆ๋‹ค. ์ด ํŒŒ์ผ์€ init(), update(), on_message() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ณดํ†ต์˜ Lua ์Šคํฌ๋ฆฝํŠธ์ด๋ฉฐ OpenGL ๋ Œ๋”๋ง API ์™€ ์†Œํ†ตํ•˜๋Š”๋ฐ ์ฃผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ "Builtins" ํด๋” ์•ˆ์—์„œ ๊ธฐ๋ณธ ๋ Œ๋” ์˜ค๋ธŒ์ ํŠธ("default.render")์™€ ๊ธฐ๋ณธ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ("default.render_script")๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ Œ๋” ์˜ค๋ธŒ์ ํŠธ๋Š” ํ˜„์žฌ์˜ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Defold๋Š” ํœด๋Œ€์žฅ์น˜์—์„œ OpenGL ES 2.0 ๊ธฐ๋ฐ˜์œผ๋กœ ๋ Œ๋”๋ง ๋ฉ๋‹ˆ๋‹ค. ๋ฐ์Šคํฌํƒ‘์—์„œ๋Š” ๋ณดํ†ต์˜ Open GL์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ OpenGL ES 2.0์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‰์ด๋”๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ ์ด๋Š” ๋ฐ์Šคํฌํƒ‘๊ณผ ํœด๋Œ€์žฅ์น˜๊ฐ„์˜ ์ƒํ˜ธ ํ˜ธํ™˜์„ ๊นจํŠธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Builtin render

Default render

์ปค์Šคํ…€ ๋ Œ๋”๋Ÿฌ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. "default.render" ํŒŒ์ผ๊ณผ "default.render_script" ํŒŒ์ผ์„ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.
  2. ๋ณต์‚ฌํ•œ ํŒŒ์ผ๋“ค์„ ๋‹น์‹ ์˜ ํ”„๋กœ์ ํŠธ์˜ ์•„๋ฌด๋ฐ๋‚˜ ("render" ํด๋” ๊ฐ™์€ ๊ณณ)์— ๋ถ™์—ฌ ๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค.
  3. ๋ณต์‚ฌํ•œ "default.render" ํŒŒ์ผ์„ ์—ฐ ํ›„ (์ด๋ฆ„ ๋ฐ”๊ฟ”๋„ ๋จ) script ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜์—ฌ ๋ณต์‚ฌํ•œ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
  4. "game.project" ์„ค์ • ํŒŒ์ผ์—์„œ Bootstrap ํ•ญ๋ชฉ ์•„๋ž˜์˜ render ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜์—ฌ ์œ„์—์„œ ๋ณต์‚ฌํ•œ "default.render" ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

๋ฌผ๋ก  ๊ทธ๋ƒฅ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ƒˆ๋กœ ์ƒ์„ฑํ•ด๋„ ๋˜์ง€๋งŒ, Defold์™€ OpenGL ES ๋ Œ๋”๋ง์„ ์ฒ˜์Œ ๋‹ค๋ค„๋ณด๋Š” ์‚ฌ์šฉ์ž๋ผ๋ฉด ๊ธฐ์กด ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ณต์‚ฌํ•ด์„œ ํŽธ์ง‘ํ•˜๋Š” ๋ฐฉ์‹์ด ์ข‹์€ ์ ‘๊ทผ๋ฒ•์ž…๋‹ˆ๋‹ค.

๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ๋Š” ๊ฒŒ์ž„์˜ ๋ผ์ดํ”„์‚ฌ์ดํด ๋‚ด์—์„œ ํŠน๋ณ„ํ•œ ์œ„์น˜์— ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ Application lifecycle ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Render predicates

render predicates(๋ Œ๋” ์ˆ ์–ด or ์กฐ๊ฑด์ž)๋Š” ์˜ค๋ธŒ์ ํŠธ์˜ ๊ทธ๋ฆฌ๊ธฐ ์ˆœ์„œ(draw order)๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. predicate๋Š” ๋ฉ”ํ„ฐ๋ฆฌ์–ผ ํƒœ๊ทธ์˜ ์„ ํƒ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฌด์—‡์„ ๊ทธ๋ฆด ๊ฒƒ์ธ์ง€ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ํ™”๋ฉด์— ๊ทธ๋ ค์ง€๋Š” ๊ฐ ์˜ค๋ธŒ์ ํŠธ๋Š” ๋ฉ”ํ„ฐ๋ฆฌ์–ผ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์–ด๋–ป๊ฒŒ ์ •ํ™•ํžˆ ํ™”๋ฉด์— ๊ทธ๋ฆด์ง€, ์–ด๋–ค ์‰์ด๋” ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ• ์ง€๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค. ๋ฉ”ํ„ฐ๋ฆฌ์–ผ์—์„œ๋Š”, ๋ฉ”ํ„ฐ๋ฆฌ์–ผ๊ณผ ์—ฐ๊ด€๋œ ํ•œ ๊ฐœ ์ด์ƒ์˜ ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฒŒ์ž„์„ ๋นŒ๋“œํ•  ๋•Œ ๋น„ํŠธ ํ•„๋“œ(bit field)๋กœ ์ปดํŒŒ์ผ ๋˜์ง€๋งŒ, ์—๋””ํ„ฐ์ƒ์—์„œ๋Š” ๋ณดํ†ต์˜ ํ…์ŠคํŠธ ํƒœ๊ทธ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค. ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์—์„œ ํ•œ๋‘๊ฐœ ๋ Œ๋” predicate๋ฅผ ๋งŒ๋“ค๊ณ  ์ด predicate๊ฐ€ ์†ํ•  ํƒœ๊ทธ๋ฅผ ์ง€์ •ํ•ด ๋ณด์„ธ์š”. ๋งˆ์ง€๋ง‰์œผ๋กœ predicate๋ฅผ ๊ทธ๋ฆด ๋•Œ์—๋Š”, predicate์— ์ง€์ •๋œ ๋ชฉ๋ก๊ณผ ์ผ์น˜ํ•˜๋Š” ํƒœ๊ทธ๋ฅผ ํฌํ•จํ•œ ๋ฉ”ํ„ฐ๋ฆฌ์–ผ์ด ์žˆ๋Š” ๊ฐ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ๋ฉ”ํ„ฐ๋ฆฌ์–ผ์— ๋Œ€ํ•œ ๋” ์ž์„ธํ•œ ์„ค๋ช…์€ Material ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Render predicate

The render script

๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š”์ง€ ๋” ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ธฐ๋ณธ ๋‚ด์žฅ๋œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์กฐ๊ธˆ ์ˆ˜์ •ํ•œ ๋ฒ„์ „์œผ๋กœ ์ž์„ธํžˆ ์‚ดํŽด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. init() ์ด ์‹œ์ž‘๋˜๋ฉด predicate, view, clear color๋ฅผ ์„ค์ •ํ•˜๋Š”๋ฐ, ์ด ๋ณ€์ˆ˜๋“ค์€ ์‹ค์ œ ๋ Œ๋”๋ง ์ค‘์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

init()

function init(self)
    -- render predicate๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ predicate๋Š” ์ž๊ธฐ ์Šค์Šค๋กœ ๋“œ๋กœ์šฐ๋˜๊ณ  ์ด ๋“œ๋กœ์šฐ๋“ค ์‚ฌ์ด์—์„œ OpenGL์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    self.tile_pred = render.predicate({"tile"})
    self.gui_pred = render.predicate({"gui"})
    self.text_pred = render.predicate({"text"})
    self.particle_pred = render.predicate({"particle"})
    self.model_pred = render.predicate({"model"})

    self.clear_color = vmath.vector4(0, 0, 0, 0)
    self.clear_color.x = sys.get_config("render.clear_color_red", 0)
    self.clear_color.y = sys.get_config("render.clear_color_green", 0)
    self.clear_color.z = sys.get_config("render.clear_color_blue", 0)
    self.clear_color.w = sys.get_config("render.clear_color_alpha", 0)

    -- ์‚ฌ์šฉํ•  view matrix๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด  "set_view_projection" ๋ฉ”์„ธ์ง€๋ฅผ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ๋กœ ์ „์†กํ•˜๊ณ  ์นด๋ฉ”๋ผ๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๊ฐ’์œผ๋กœ view matrix๋ฅผ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    self.view = vmath.matrix4()
end

์ปค์Šคํ…€ํ•œ ํ”„๋กœ์ ํŠธ ์…‹ํŒ…์„ ์–ด๋–ป๊ฒŒ ์ •์˜ํ•˜๊ณ  ์‚ฌ์šฉํ• ์ง€์— ๋Œ€ํ•œ ์ •๋ณด๋Š” Project settings ๋ฌธ์„œ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒŒ์ž„ ์นด๋ฉ”๋ผ๊ฐ€ ๋™์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ๊ณ  ์‹ถ๋‹ค๋ฉด Camera ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

update()

update() ํ•จ์ˆ˜๋Š” ๋งค ํ”„๋ ˆ์ž„ ๋งˆ๋‹ค ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” OpenGL ES API(OpenGL Embedded Systems API)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹ค์ œ ๋“œ๋กœ์ž‰์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. update() ํ•จ์ˆ˜์—์„œ ๋ฌด์Šจ์ผ์ด ๋ฒŒ์–ด์ง€๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” OpenGL์ด ๋™์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•ด์•ผ๋งŒ ํ•ฉ๋‹ˆ๋‹ค. OpenGL ES์—๋Š” ํ›Œ๋ฅญํ•œ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋งŽ์ด ์žˆ์œผ๋ฉฐ https://www.khronos.org/opengles/ ๊ณต์‹ ์‚ฌ์ดํŠธ๊ฐ€ ์ดํ•ด๋ฅผ ์œ„ํ•œ ์ข‹์€ ์ถœ๋ฐœ์ ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์˜ˆ์ œ์—๋Š” 3D ๋ชจ๋ธ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ทธ๋ฆฌ๋Š”๋ฐ ํ•„์š”ํ•œ ์„ค์ •์„ ํ•˜๋Š” ๋‚ด์žฅ ์Šคํฌ๋ฆฝํŠธ์— ๋Œ€ํ•œ ์ฃผ์š”์‚ฌํ•ญ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์—์„œ ๋ณด์•˜๋“ฏ์ด, self.model_pred predicate๊ฐ€ ๊ตฌ์„ฑ๋˜๊ณ  ๋‹ค๋ฅธ ๊ณณ์—์„œ ์ด predicate์— ํ•ด๋‹นํ•˜๋Š” ๋ฉ”ํ„ฐ๋ฆฌ์–ผ์ด ์ •์˜๋˜์–ด 3D ๋ชจ๋ธ ์ปดํฌ๋„ŒํŠธ์— ๋ฐ˜์˜๋˜์—ˆ์Šต๋‹ˆ๋‹ค. update() ์ฝ”๋“œ๋Š” ์ด predicate์— ๋Œ€ํ•œ ํŠน์ •ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ํ•„์š”๋กœ ํ•ฉ๋‹ˆ๋‹ค.

function update(self)
    -- depth buffer๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก depth mask๋ฅผ ์„ค์ •ํ•จ
    render.set_depth_mask(true)

    -- ํด๋ฆฌ์–ด ์ปฌ๋Ÿฌ๊ฐ’(clear color)์œผ๋กœ color buffer๋ฅผ ์ง€์šฐ๊ณ  depth buffer๋ฅผ 1.0์œผ๋กœ ์„ค์ •ํ•จ
    -- ์ •์ƒ์ ์ธ depth ๊ฐ’์€ 0.0(near)์—์„œ 1.0(far) ์‚ฌ์ด์ด๋ฏ€๋กœ ๋ฒ„ํผ์—์„œ ๊ฐ’๋“ค์„ ์ตœ๋Œ€ํ™”(maximizing)ํ•˜๋ฉด ๊ทธ๋ ค์ง„ ๋ชจ๋“  ํ”ฝ์…€์ด 1.0๋ณด๋‹ค ๊ฐ€๊นŒ์›Œ์ง€๊ธฐ ๋•Œ๋ฌธ์— ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ทธ๋ ค์ง€๊ฒŒ ๋˜๋ฉฐ ๊นŠ์ด ํ…Œ์ŠคํŠธ(depth testing)๊ฐ€ ์ˆ˜ํ–‰๋จ
    render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color, [render.BUFFER_DEPTH_BIT] = 1, [render.BUFFER_STENCIL_BIT] = 0})

    -- ๋ทฐํฌํŠธ๋ฅผ ์œˆ๋„์šฐ์˜ ์ฐฝ ํฌ๊ธฐ๋กœ ์„ค์ •ํ•จ
    render.set_viewport(0, 0, render.get_window_width(), render.get_window_height())

    -- ๋ทฐ๋ฅผ ์ €์žฅํ•œ ๋ทฐ ๊ฐ’์œผ๋กœ ์„ค์ •ํ•จ(์นด๋ฉ”๋ผ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ด์šฉํ•ด ์„ค์ • ๊ฐ€๋Šฅ)
    render.set_view(self.view)

    -- 2D ๊ณต๊ฐ„ ๋ Œ๋”๋งํ•˜๊ธฐ
    render.set_depth_mask(false)
    render.disable_state(render.STATE_DEPTH_TEST)
    render.disable_state(render.STATE_STENCIL_TEST)
    render.enable_state(render.STATE_BLEND)
    render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA)
    render.disable_state(render.STATE_CULL_FACE)

    -- ์ง๊ต(orthographic) ์ƒํƒœ๋กœ ํˆฌ์˜(projection)๋ฐฉ์‹์„ ์„ค์ •ํ•˜์—ฌ -200์—์„œ 200 Z-depth ์‚ฌ์ด๊นŒ์ง€๋งŒ ๋ Œ๋”๋งํ•จ
    render.set_projection(vmath.matrix4_orthographic(0, render.get_width(), 0, render.get_height(), -200, 200))

    render.draw(self.tile_pred)
    render.draw(self.particle_pred)

    -- 3D ๊ณต๊ฐ„ ๋ Œ๋”๋งํ•˜๊ธฐ, ํ•˜์ง€๋งŒ ์—ฌ์ „ํžˆ ์ง๊ต(orthographic) ์ƒํƒœ์ž„
    -- ํŽ˜์ด์Šค ์ปฌ๋ง(Face culling)๊ณผ ๊นŠ์ด ํ…Œ์ŠคํŠธ(depth test)๋ฅผ ํ™œ์„ฑํ™” ํ•จ
    render.enable_state(render.STATE_CULL_FACE)
    render.enable_state(render.STATE_DEPTH_TEST)
    render.set_depth_mask(true)
    render.draw(self.model_pred)
    render.draw_debug3d()

    -- ๋งˆ์ง€๋ง‰์œผ๋กœ GUI ๋ Œ๋”๋งํ•˜๊ธฐ
    render.set_view(vmath.matrix4())
    render.set_projection(vmath.matrix4_orthographic(0, render.get_window_width(), 0, render.get_window_height(), -1, 1))

    render.enable_state(render.STATE_STENCIL_TEST)
    render.draw(self.gui_pred)
    render.draw(self.text_pred)
    render.disable_state(render.STATE_STENCIL_TEST)

    render.set_depth_mask(false)
    render.draw_debug2d()
end

์ž, ์ด์ œ ๋‹จ์ˆœํ•˜๊ณ  ์ง๊ด€์ ์ธ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์™„์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ๋Š” ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ํ™”๋ฉด์„ ๊ทธ๋ฆฌ์ง€๋งŒ, ๋งŒ์•ฝ ๋ Œ๋” ์ƒํƒœ(render states)๋ฅผ ๋„์ž…ํ•˜์—ฌ ๋‹ค๋ฅธ ๊ณณ์—์„œ ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ(render pipeline)์„ ์ œ์–ดํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ์š”?

on_message()

์ด ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ ๋˜ํ•œ Defold์˜ ๋ฉ”์„ธ์ง€ ์ „๋‹ฌ ์„ธ์ƒ์—์„œ๋Š” ๋ณดํ†ต์˜ ์‹œ๋ฏผ๋“ค๊ณผ ๋‹ค๋ฅผ ๋ฐ” ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ƒฅ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์— on_message() ํ•จ์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฒŒ์ž„์˜ ๋‹ค๋ฅธ ํŒŒํŠธ์—์„œ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์˜ ๋™์ž‘์— ์˜ํ–ฅ์„ ์ฃผ๋„๋ก ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์— ์ •๋ณด๋ฅผ ๋ณด๋‚ด๋Š” ์™ธ๋ถ€ ์˜ค๋ธŒ์ ํŠธ์— ๋Œ€ํ•œ ์˜ˆ์ œ๋กœ๋Š” ์นด๋ฉ”๋ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(์ž์„ธํ•œ ๋‚ด์šฉ์€ Camera ๋ฌธ์„œ ์ฐธ๊ณ ). ์นด๋ฉ”๋ผ ํฌ์ปค์Šค๊ฐ€ ์žˆ๋Š” ์นด๋ฉ”๋ผ ์ปดํฌ๋„ŒํŠธ๋Š” ์ž๋™์ ์œผ๋กœ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์— view์™€ projection์„ ๋ณด๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด ์ผ๋ฐ˜ ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์™€ ํ†ต์‹ ํ•˜๋ ค๋ฉด ํŠน์ˆ˜ํ•œ ์†Œ์ผ“์ธ @render๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function on_message(self, message_id, message)
    if message_id == hash("clear_color") then
        -- ์–ด๋””์„ ๊ฐ€ ํด๋ฆฌ์–ด ์ปฌ๋Ÿฌ(clear color) ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋ƒ„
        self.clear_color = message.color
    elseif message_id == hash("set_view_projection") then
        -- ์นด๋ฉ”๋ผ ํฌ์ปค์Šค๋ฅผ ๊ฐ€์ง„ ์นด๋ฉ”๋ผ ์ปดํฌ๋„ŒํŠธ๊ฐ€ @render ์†Œ์ผ“์œผ๋กœ set_view_projection ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋ƒ„. ๋ Œ๋”๋ง์˜ view(๊ทธ๋ฆฌ๊ณ  ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ projection)๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ์นด๋ฉ”๋ผ ์ •๋ณด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ
        -- ํ˜„์žฌ, ์ง๊ต ์ƒํƒœ๋กœ(orthogonally) ๋ Œ๋”๋ง ์ค‘์ด๋ฏ€๋กœ ์นด๋ฉ”๋ผ ํˆฌ์˜(projection)์ด ํ•„์š” ์—†์Œ
        self.view = message.view
    end
end

์œ„์˜ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์™€ on_message() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์•„๋ž˜์ฒ˜๋Ÿผ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด์„œ clear color๋ฅผ ๋ฉ‹์ง„ ๋‹คํฌ ์Šคํ‹ธ ๋ธ”๋ฃจ(dark steel blue) ์ƒ‰๊น”๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

msg.post("@render:", "clear_color", { color = vmath.vector4(0.3, 0.4, 0.5, 0) })

System messages

@render ์†Œ์ผ“์€ ๋ช‡ ๊ฐ€์ง€ ๋‚ด์žฅ ๋ฉ”์„ธ์ง€๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ์„ , ์œˆ๋„์šฐ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๊ฒฝ์šฐ ์—”์ง„์ด ๋ณด๋‚ด์ฃผ๋Š” window_resized ๋ฉ”์„ธ์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์Šคํฌํƒ‘์—์„œ๋Š” ๊ฒŒ์ž„ ์ฐฝ ํฌ๊ธฐ๊ฐ€ ์กฐ์ ˆ๋  ๊ฒฝ์šฐ, ๋ชจ๋ฐ”์ผ์—์„œ๋Š” orientation์ด ๋ฐ”๋€” ๊ฒฝ์šฐ ์ด ๋ฉ”์„ธ์ง€๊ฐ€ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

function on_message(self, message_id, message)
  if message_id == hash("window_resized") then
    -- ์œˆ๋„์šฐ๊ฐ€ ๋ฆฌ์‚ฌ์ด์ง• ๋จ. ์ƒˆ ํฌ๊ธฐ๊ฐ€ message.width์™€ message.height์— ํฌํ•จ๋จ
    ...
  end
end

๋˜ํ•œ ํ…์ŠคํŠธ์™€ ์„ ์„ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„ธ์ง€๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

-- (1000, 1000)์ขŒํ‘œ๊นŒ์ง€ ํฐ์ƒ‰ ์„ ์„ ๊ทธ๋ฆผ
msg.post("@render:", "draw_line", { start_point = vmath.vector3(0, 0, 0), end_point = vmath.vector3(1000, 1000, 0), color = vmath.vector4(1, 1, 1, 1) } )

-- 500, 500 ์ขŒํ‘œ์— ํ…์ŠคํŠธ ๋ฉ”์„ธ์ง€๋ฅผ ๊ทธ๋ฆผ
msg.post("@render:", "draw_text", { text = "Hello world!", position = vmath.vector3(500, 500, 0) } )

์ด ๋ฉ”์„ธ์ง€๋“ค์€ ๋””๋ฒ„๊น… ์ •๋ณด๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๋””๋ฒ„๊ทธ ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๊ฑฐ๋‚˜ ray_casts๋‚˜ vector๋‚˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์œ„ํ•œ ๊ฐœ๋ฐœ ํ†ต๊ณ„ ๋”ฐ์œ„๋ฅผ ์‰ฝ๊ฒŒ ์‹œ๊ฐํ™” ํ•˜๋Š”๋ฐ ์œ ์šฉํ•˜๋ฉฐ, ์•„๋ž˜์˜ ์„ค๋ช…์ฒ˜๋Ÿผ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์™€ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • draw_line ๋ฉ”์„ธ์ง€๋ฅผ ํ†ตํ•ด ์”ฌ(scene)์— ์ถ”๊ฐ€๋œ ๋ชจ๋“  ์„ (line)๋“ค์€ render.draw_debug3d() ํ˜ธ์ถœ์— ์˜ํ•ด ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค.

  • draw_text ๋ฉ”์„ธ์ง€๋ฅผ ํ†ตํ•ด ์”ฌ(scene)์— ์ถ”๊ฐ€๋œ ๋ชจ๋“  ํ…์ŠคํŠธ(text)๋“ค์€ ๋‚ด์žฅ๋œ "system_font"๋กœ ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ ํฐํŠธ๋Š” "text" ํƒœ๊ทธ๊ฐ€ ์žˆ๋Š” ๋ฉ”ํ„ฐ๋ฆฌ์–ผ์„ ๊ฐ€์ง€๋ฏ€๋กœ ์œ„์˜ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ ๋‚ด์šฉ์ค‘์—์„œ "self.text_pred" predicate์— ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค.

toggle_profile ๋ฉ”์„ธ์ง€๋ฅผ @system ์†Œ์ผ“์œผ๋กœ ๋ณด๋‚ด์„œ ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ๋Š” ๋น„์ฃผ์–ผ ํ”„๋กœํŒŒ์ผ๋Ÿฌ(visual profiler)๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ ์ฒ˜๋ฆฌ ๊ฐ€๋Šฅํ•œ ๋ Œ๋”๋Ÿฌ์™€๋Š” ๋‹ค๋ฅธ ํŒŒํŠธ์ด๋ฏ€๋กœ ๋‹น์‹ ์˜ ๋ Œ๋” ์Šคํฌ๋ฆฝํŠธ์™€๋Š” ๋ถ„๋ฆฌ๋˜์–ด ๊ทธ๋ ค์ง‘๋‹ˆ๋‹ค.