728x90

 

์ด๋ฒคํŠธ ํ ํŒจํ„ด

 

๋ฉ”์‹œ์ง€๋‚˜ ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ด๋Š” ์‹œ์ ๊ณผ ์ฒ˜๋ฆฌํ•˜๋Š” ์‹œ์ ์„ ๋””์ปคํ”Œ๋งํ•จ

๋ณดํ†ต์˜ ์ด๋ฒคํŠธ๋Š” ๋™๊ธฐ์ ์œผ๋กœ ์—ฐ์‚ฐ

๋™๊ธฐ์ (Synchronouse) ๋น„๋™๊ธฐ์ (Asynchronous)
์–ด๋–ค ์ž‘์—…์„ ์š”์ฒญํ–ˆ์„ ๋•Œ ๊ทธ ์ž‘์—…์ด ์ข…๋ฃŒ๋ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฐ ํ›„ ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹
์–ด๋–ค ์ž‘์—…์„ ์š”์ฒญํ–ˆ์„ ๋•Œ ๊ทธ ์ž‘์—…์ด ์ข…๋ฃŒ๋ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ž‘์—…์„ ํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€, ์š”์ฒญํ–ˆ๋˜ ์ž‘์—…์ด ์ข…๋ฃŒ๋˜๋ฉด ๊ทธ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹
์„œ๋ธŒ๋ฃจํ‹ด ๊ฐ„์— ๋ช…ํ™•ํ•œ ์‹คํ–‰ ์ˆœ์„œ ์กด์žฌ ์„œ๋ธŒ๋ฃจํ‹ด ๊ฐ„์— ๋ช…ํ™•ํ•œ ์‹คํ–‰ ์ˆœ์„œ ์กด์žฌํ•˜์ง€ ์•Š์Œ

 

์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ด๊ณ , ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฉˆ์ถฐ๋ฒ„๋ฆฌ๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒ

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ ์ž ๋‚˜์˜จ ๊ฒƒ์ด ์ด๋ฒคํŠธ ํ ํŒจํ„ด์ด๋‹ค

 

์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ, ๋ช…๋ น์„ ๋‹ด์•„ ๋‘˜ ๊ณต๊ฐ„์ด ํ•„์š”ํ•œ๋ฐ Queue์— ์ด๋ฒคํŠธ๋ฅผ ๋‹ด์•„๋‘”๋‹ค

 

ํŠœํ† ๋ฆฌ์–ผ ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

 

๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ์ˆœ์ฐจ์ ์œผ๋กœ ์ง„ํ–‰์ด ๋˜๊ธธ ์›ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

์˜ˆ๋ฅผ ๋“ค์–ด ์—…์ ์„ ๋‹ฌ์„ฑํ–ˆ์„ ๋•Œ,

์—…์  ๋‹ฌ์„ฑ์— ๋Œ€ํ•œ ๋ฐ˜์‘๋“ค์ด ๋‚˜ํƒ€๋‚˜์•ผํ•จ

๋งŒ์•ฝ ์—…์  ๋‹ฌ์„ฑ์ด Popup๊ณผ Sound๋ฅผ ์ถœ๋ ฅํ•˜๋Š”๋ฐ,

์—ฌ๋Ÿฌ๊ฐ€์ง€ ์—…์ ์„ ํ•œ๋ฒˆ์— ๋‹ฌ์„ฑํ–ˆ์„ ๊ฒฝ์šฐ ํ•ด๋‹น ์—…์  ๋‹ฌ์„ฑ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋™์‹œ์ ์œผ๋กœ ์ถœ๋ ฅํ•˜๋ฉด ์•ˆ๋˜๋Š” ๊ฒฝ์šฐ FIFO ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ์ด๋ฒคํŠธ ํ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค

ํ์— ๋„ฃ๋Š” ์ด์œ ๋Š” ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค

์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ด๊ณ , ์ฒ˜๋ฆฌํ•˜๋Š” ๋™์•ˆ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฉˆ์ถฐ๋ฒ„๋ฆฌ๋Š” ์ƒํ™ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค

์ด๋ฒคํŠธ ํ๋Š” ๊ด€์ฐฐ์ฐจ ํŒจํ„ด์˜ ๋น„๋™๊ธฐํ˜•

 

๊ด€์ฐฐ์ž, ๋ช…๋ น ํŒจํ„ด ์ด๋ฒคํŠธ ํ ํŒจํ„ด
๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ๊ณณ๊ณผ ๋ฐ›๋Š” ๊ณณ์œผ๋กœ ๋ถ„๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด๋‚ด๋Š” ์‹œ์ ๊ณผ ๋ฐ›๋Š” ์‹œ์ ์„ ๋ถ„๋ฆฌํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ

 

 

์ฃผ์˜์‚ฌํ•ญ

  1. ๋ชจ๋“  ์ด๋ฒคํŠธ, ๋ฉ”์‹œ์ง€ ์‹œ์Šคํ…œ์€ ํ”ผ๋“œ๋ฐฑ ๋ฃจํ”„๊ฐ€ ์ƒ๊ธฐ๋ฉด ์•ˆ๋จ
  2. ์œ ๊ธฐ์ ์œผ๋กœ ๊ณ„์† ์—ฐ๊ฒฐ๋˜๋Š” ์ด๋ฒคํŠธ๋“ค์„ ๋„ฃ์œผ๋ฉด ์ด๋ฒคํŠธ ํ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ์˜๋ฏธ๊ฐ€ ์—†์–ด์ง
  3. ์ด๋ฒคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ ๋‚ด์—์„œ๋Š” ์ด๋ฒคํŠธ๋ฅผ ๋ณด๋‚ด์ง€ ์•Š์•„์•ผํ•จ

 

 

 

๋ฐ˜์‘ํ˜•

'๊ณต๋ถ€ > Design Pattern' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

์‹ฑ๊ธ€ํ†ค(Singleton) ํŒจํ„ด์ด๋ž€?  (0) 2021.12.15
728x90

์›๋ฌธ: https://benui.ca/unreal/ui-cpp-basics/

 

Unreal์„ ์œ„ํ•œ ๋งŽ์€ UI ํŠœํ† ๋ฆฌ์–ผ์€ Blueprint์— ์ดˆ์ ์„ ๋งž์ถ”๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋” ๋„“์€ ๋งค๋ ฅ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ์ „๋ฌธ๊ฐ€ ์ˆ˜์ค€์˜ UI๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด C++์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์™œ ์šฐ๋ฆฌ๋Š” C++์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š”๊ฐ€?

์šฐ์„ , ๋ถ„๋ช…ํžˆ ์šฐ๋ฆฌ๋Š” Blueprint๋กœ ๋ชจ๋“  ๊ฒƒ์„ ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์™œ ์šฐ๋ฆฌ๋Š” C++๋กœ UI๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•˜๋‚˜์š”? ๋ผ๋Š” ์งˆ๋ฌธ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋งž์„์ˆ˜๋„ ์žˆ์ง€๋งŒ ์•„๋‹์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. Blueprint๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ „์ฒด ๊ฒŒ์ž„์˜ UI๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๊ทธ ๊ณผ์ •์—์„œ ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ๋ฌธ์ œ์— ๋ถ€๋”ชํž ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • Blueprint ๊ธฐ๋ฐ˜์˜ ๋Œ€ํ˜• UI์—์„œ ์„ฑ๋Šฅ ๋ฌธ์ œ์— ๋ถ€๋”ชํž ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค. ์ž‘์€ 1ํšŒ์šฉ Blueprint๋Š” ๊ดœ์ฐฎ์ง€๋งŒ ๋ชจ๋“  ํ”„๋ ˆ์ž„์œผ๋กœ ๋ถˆ๋ฆฌ๋Š” ํฌ๊ณ  ๋ณต์žกํ•œ ๋กœ์ง์˜ ๊ฒฝ์šฐ Blueprint ๊ธฐ๋ฐ˜์˜ UI๊ฐ€ ์‹ค์ œ๋กœ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • Blueprint์—์„œ ๋ณต์žกํ•œ ๋…ผ๋ฆฌ๋Š” ์•…๋ชฝ์„ ๊ณ„์† ์œ ์ง€์‹œํ‚ต๋‹ˆ๋‹ค. ํฐ Blueprint ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ž‘์„ฑํ•œ ์‚ฌ๋žŒ์€ ์ŠคํŒŒ๊ฒŒํ‹ฐ ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋Š์ž„์—†๋Š” ์‹ธ์›€์˜ ์›์ธ์ด ๋  ๊ฒƒ ์ž…๋‹ˆ๋‹ค.
  • ์ˆ˜์ง‘, ์ฒ˜๋ฆฌ ๋ฐ ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์  ํ…Œ์ด์…˜์„ ๋ถ„๋ฆฌํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. Blueprint ์ „์šฉ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋กœ ๋‹ค๋ฅธ ์†Œ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ๊ณผ ํ‘œ์‹œ๋ฅผ ์œ„ํ•ด ํฌ๋งทํ™”ํ•˜๋Š” ๊ฒƒ์„ ์‰ฝ๊ฒŒ ํ˜ผํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋””์Šคํ”Œ๋ ˆ์ด ๊ทธ๋ž˜ํ”„ ๋…ธ๋“œ๊ฐ€ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๋…ธ๋“œ์™€ ๋งค์šฐ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํ–ฅํ›„ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋•Œ ์‹ค์งˆ์ ์ธ ์–ด๋ ค์›€์„ ์•ผ๊ธฐํ•ฉ๋‹ˆ๋‹ค.
  • ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ํ•œ ๋ฒˆ์— UI ์ž‘์—…์„ ํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. Blueprint๋Š” ์ด์ง„ ์ž์‚ฐ์œผ๋กœ ๋ณ‘ํ•ฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ํ•œ๋ฒˆ์— ํ•œ ์‚ฌ๋žŒ๋งŒ ํŽธ์ง‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. UI ์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ ์œ„์ ฏ์˜ ๋ชจ์–‘์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ Blueprint ๋กœ์ง์„ ์—…๋ฐ์ดํŠธํ•˜๋ ค๋ฉด ์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ๋กœ์ง์ด C++์ด๋ฉด ๋‘ ์‚ฌ๋žŒ ๋ชจ๋‘ ์„œ๋กœ์˜ ๋ฐœ๊ฐ€๋ฝ์„ ๋ฐŸ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋‚ฎ์Šต๋‹ˆ๋‹ค.

C++์„ ์‚ฌ์šฉํ•œ UI๋ฅผ ๋งŒ๋“œ๋Š” ์„ธ๊ฐ€์ง€ ๋ฐฉ๋ฒ•

์—ฌ๊ธฐ์„œ ์ผ์ด ์กฐ๊ธˆ ๊นŒ๋‹ค๋กœ์›Œ์ง‘๋‹ˆ๋‹ค. ๋ชจ๋“  UI ๋””์ž์ธ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” 100๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์„ธ ๊ฐ€์ง€ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋‹ค์Œ ํŠœํ† ๋ฆฌ์–ผ์—์„œ ๊ฐœ๋ณ„์ ์œผ๋กœ ๋‹ค๋ฃจ๊ฒ ์ง€๋งŒ ๋Œ€๋žต ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค

  • UUserWidget ์˜ Subclassing(๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ๋ชฉ์ ์œผ๋กœ ์ƒ์†์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ)
  • Subclassing ํ˜น์€ ์ƒˆ๋กœ์šด UMG ์œ„์ ฏ ์ƒ์„ฑ
  • Subclassing ํ˜น์€ ์ƒˆ๋กœ์€ Slate ์œ„์ ฏ ์ƒ์„ฑ

์ด๊ฒƒ๋“ค์€ ๊ฐ๊ฐ ์žฅ์ ๊ณผ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ๋“ค์ด ์˜๋งˆํ•˜๋Š” ๋ฐ”๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” Slate์™€ UMG์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์–˜๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Slate์™€ UMG

์ฒซ ๋ฒˆ์งธ C++ ๊ธฐ๋ฐ˜ UserWidget์„ ๋งŒ๋“ค๋ ค๋ฉด UUserWidget์˜ ํ•˜์œ„ ํด๋ž˜์Šค์ธ C++ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ์ด์ œ ํŽธ์ง‘๊ธฐ์—์„œ UI๋ฅผ ๋งŒ๋“ค๊ณ  ํŒ”๋ ˆํŠธ์— ์žˆ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์œ„์ ฏ์˜ ๋ชฉ์ ๊ณผ ๊ธฐ๋Šฅ์„ ์ดํ•ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์—๋””ํ„ฐ์™€ ๋ธ”๋ฃจํ”„๋ฆฐํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ UI๋ฅผ ์ƒ์„ฑํ•ด๋ด„์œผ๋กœ์จ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋ฐฉ๋ฒ•์€ ์‹œ๋ฆฌ์ฆˆ ์†Œ๊ฐœ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

 

๋‹ค์Œ ๋‹จ๊ณ„๋Š” C++์—์„œ ์œ„์ ฏ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด๋ฒˆ ์‹œ๋ฆฌ์ฆˆ์˜ ์„œ๋ก ์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด Unreal(4.15 ๊ธฐ์ค€)์—๋Š” UMG์™€ Slate ๋‘ ๊ฐ€์ง€ UI ์‹œ์Šคํ…œ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

Slate๋Š” ์˜ค๋ž˜๋œ Unreal UI ์‹œ์Šคํ…œ์ด๊ณ , UMG์™€ ์—๋””ํ„ฐ๊ฐ€ ๊ธฐ๋ฐ˜์„ ๋‘๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์ ฏ ์„ค์ •์„ ๋‹จ์ˆœํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๊ณ ์ „์ ์ธ ์™ธ๊ด€์˜ C++์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. "์˜ค๋ž˜๋œ" ์‹œ์Šคํ…œ์ด๋ผ๊ณ  ํ•ด์„œ ์˜ค๋ž˜๋œ ๊ฒƒ์€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. UI์— ๋” ๋ณต์žกํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด ์Šฌ๋ ˆ์ดํŠธ๋ฅผ ์ ์ฐจ ๋ฐฐ์›Œ์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

UMG๋Š” Unreal 4์˜ ์ผ๋ถ€๋กœ ์ถ”๊ฐ€๋œ ์ƒˆ๋กœ์šด UI ์‹œ์Šคํ…œ์ž…๋‹ˆ๋‹ค. Blueprint ์นœํ™”์ ์œผ๋กœ ์„ค๊ณ„๋˜์—ˆ์œผ๋ฉฐ ๋””์ž์ด๋„ˆ๊ฐ€ ํŽธ์ง‘๊ธฐ์—์„œ UI๋ฅผ ์‹œ๊ฐ์ ์œผ๋กœ ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ UMG ์œ„์ ฏ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฑฐ์˜ ๋™์ผํ•œ ์ด๋ฆ„์˜ Slate ํด๋ž˜์Šค๋ฅผ ๋‚ด๋ถ€์— ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. **Slate ํด๋ž˜์Šค๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋กœ์ง์„ ์ฒ˜๊ธฐํ•˜๊ณ  ํ•ด๋‹น UMG ํด๋ž˜์Šค๋Š” ๊ทธ๊ฒƒ์„ ๊ฐ์‹ธ๋Š” wrapper์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด UImage๋Š” UMG ํด๋ž˜์Šค์ด๋ฉฐ ๋‚ด๋ถ€์— SImage ์ธ์Šคํ„ด์Šค๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

 

๋จผ์ €, ์—ญ์‚ฌ์˜ ์ž‘์€ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ ๋„˜์–ด๊ฐ€์ง€ ๋งˆ์„ธ์š”. ์—ฌ๋Ÿฌ๋ถ„์˜ ์ดํ•ด๋ฅผ ์œ„ํ•ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!

 

4.0 ๋ฒ„์ „ ์ด์ „์—๋Š” Unreal์˜ UI๊ฐ€ Slate๋ผ๋Š” ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋งŒ๋“ค์–ด์กŒ์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ํ•œ ๊ฐ„๋‹จํ•˜๊ฒŒ C++์˜ UI๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์ค‘์— ํŠœํ† ๋ฆฌ์–ผ ์‹œ๋ฆฌ์ฆˆ์—์„œ ์—ฌ๋Ÿฌ๋ถ„๋„ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์–ธ๋ฆฌ์–ผ ์—”์ง„ 4.0 ๋ฒ„์ „์œผ๋กœ ์—ํ”ฝ์€ ๊ทธ๋“ค์˜ ์ƒˆ๋กœ์šด UI ์‹œ์Šคํ…œ์ธ UMG๋ฅผ ์ถœ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. UMG๋Š” ํšจ๊ณผ์ ์œผ๋กœ Slate๋ฅผ ๊ฐ์‹ธ๋Š” wrapper ์ด๊ณ , Blueprints์—์„œ ๋” ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  UI ๋””์ž์ด๋„ˆ๊ฐ€ ์–ธ๋ฆฌ์–ผ ์—๋””ํ„ฐ ๋‚ด์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ UI๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

Slate๊ฐ€ ๋…ผ์˜ํ•  ๋ชจ๋“  UMG์‹œ์Šคํ…œ์˜ ๊ธฐ์ดˆ๊ฐ€ ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์Šฌ๋กฏ, ๋‹ค์–‘ํ•œ ์œ„์ ฏ, ์œ„์ ฏ์— ๋Œ€ํ•œ ์˜ต์…˜ ๋“ฑ์€ Slate์™€ ๋ชจ๋‘ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. UMG๋Š” Slate๋ฅผ ์œ„ํ•œ ์—๋””ํ„ฐ ๋ฐ Blueprint์— ์ ํ•ฉํ•œ wrapper์ผ ๋ฟ์ž…๋‹ˆ๋‹ค.

์„ธ ๊ฐ€์ง€ ์ ‘๊ทผ๋ฐฉ๋ฒ•

์ด ๋ฐฉ๋ฒ•์—์„œ ๋ฒ—์–ด๋‚˜ UI์— C++ ๊ธฐ๋ฐ˜ ์œ„์ ฏ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์— ๋‚˜์—ด๋œ ๊ฒƒ์€ ์ ์ง„์ ์œผ๋กœ ๋‚ฎ์€ ์ˆ˜์ค€์˜ '๋” ๋งŽ์€ ์ž‘์—…'์ด๋ฉฐ, ๊ทธ ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์œ ์ผํ•œ '์ตœ์ƒ์˜ ๋ฐฉ๋ฒ•'์€ ์•„๋‹ˆ๋ฉฐ, ๊ฐ๊ฐ์˜ ์ ‘๊ทผ ๋ฐฉ์‹์—๋Š” ๊ฐ๊ฐ์˜ ์žฅ์ ๊ณผ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋งฅ๋ฝ์ƒ, ์—ฌ๋Ÿฌ ํ•ด ๋™์•ˆ Unreal UI ํ”„๋กœ๊ทธ๋ž˜๋จธ๋กœ ์ผํ•œ ๊ฒฝํ—˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์ปค์Šคํ…€ UUserWidget - 95%์˜ ๊ฒฝ์šฐ ์ด๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•จ
  • ์ปค์Šคํ…€ UMG/Slate subclass - 5%์˜ ๊ฒฝ์šฐ (๋งค์šฐ ํŠน์ •ํ•œ ๊ฒƒ์„ ์›ํ•  ๊ฒฝ์šฐ ์‚ฌ์šฉ์ž ์ •์˜ UMG/Slate ์„œ๋ธŒ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ฌ)

๋ชจ๋“  ๊ฒƒ์ด ๊ทธ๋ ‡๋“ฏ์ด, ๊ฐ ์ ‘๊ทผ ๋ฐฉ์‹์—๋„ ์žฅ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ Slate๋กœ ๊ฐˆ์ˆ˜๋ก, ๋” ๋งŽ์€ ์‚ฌ์šฉ์ž ์ •์˜๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, Blueprints๋กœ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์„ค์ •ํ•˜๋Š” ์ž‘์—…์ด ๋” ๋งŽ์•„์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฐ ์ ‘๊ทผ ๋ฐฉ์‹์„ ๊ฐ๊ฐ์˜ ํŠœํ† ๋ฆฌ์–ผ๋กœ ๋ถ„๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

 

 

 

 

 

 

๋ฐ˜์‘ํ˜•
728x90

์›๋ณธ : https://ogldev.org/www/tutorial38/tutorial38.html

๋ฐฐ๊ฒฝ

๋งˆ์นจ๋‚ด ์ˆ˜๋ฐฑ๋งŒ๋ช…์˜ ๋…์ž๋“ค์ด ์š”๊ตฌํ•ด์˜จ ํŠœํ† ๋ฆฌ์–ผ. ์Šคํ‚ค๋‹์œผ๋กœ๋„ ์•Œ๋ ค์ง„ ๊ณจ๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์œผ๋กœ, Assimp ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

๊ณจ๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์€ ์‚ฌ์‹ค ๋‘ ๋ถ€๋ถ„์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ๊ณผ์ •์ž…๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ๋Š” ์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ ์‹คํ–‰ํ•˜๊ณ  ๋‘ ๋ฒˆ์งธ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ์ธ ์‚ฌ์šฉ์ž(๋˜๋Š” ์ž‘์„ฑํ•œ ์—”์ง„)๊ฐ€ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๋ถ€๋ถ„์€ ๋ชจ๋ธ๋ง ์†Œํ”„ํŠธ์›จ์–ด ๋‚ด๋ถ€์—์„œ ๋ฐœ์ƒํ•˜๋ฉฐ ๋ฆฌ๊น…์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ผ์–ด๋‚˜๋Š” ์ผ์€ ์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ mesh ์•„๋ž˜ ๋ผˆ(skeleton)์˜ ๊ณจ๊ฒฉ(bones)์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

mesh๋Š” ๋ฌผ์ฒด์˜ ํ”ผ๋ถ€(์ธ๊ฐ„์ด๋“  ๊ดด๋ฌผ์ด๋“  ๋ฌด์—‡์ด๋“ )๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฉฐ skeleton์€ ์‹ค์ œ ์„ธ๊ณ„์—์„œ ์‹ค์ œ ์›€์ง์ž„์„ ๋ชจ๋ฐฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ mesh๋ฅผ ์›€์ง์ด๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์ด ์ž‘์—…์€ ๊ฐ ์ •์ ์„ ํ•˜๋‚˜ ์ด์ƒ์˜ ๋ผˆ์— ํ• ๋‹นํ•˜์—ฌ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

์ •์ ์ด ๋ผˆ์— ํ• ๋‹น๋˜๋ฉด ๋ผˆ๊ฐ€ ์ด๋™ํ•  ๋•Œ ์ •์ ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์˜ ์–‘์„ ๊ฒฐ์ •ํ•˜๋Š” ๊ฐ€์ค‘์น˜๊ฐ€ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ ๋ชจ๋“  ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์„ (์ •์ ๋‹น) 1๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๊ผญ์ง“์ ์ด ๋‘ ๋ผˆ ์‚ฌ์ด์— ์ •ํ™•ํžˆ ์œ„์น˜ํ•œ๋‹ค๋ฉด ์šฐ๋ฆฌ๋Š” ๋ผˆ๊ฐ€ ๊ผญ์ง“์ ์— ๋ฏธ์น˜๋Š” ์˜ํ–ฅ์ด ๊ฐ™์„ ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ ๋ผˆ์— 0.5์˜ ๊ฐ€์ค‘์น˜๋ฅผ ํ• ๋‹นํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ผญ์ง“์ ์ด ์™„์ „ํžˆ ๋‹จ์ผ ๋ผˆ์˜ ์˜ํ–ฅ ๋ฒ”์œ„ ๋‚ด์— ์žˆ๋Š” ๊ฒฝ์šฐ ๊ฐ€์ค‘์น˜๋Š” 1์ด ๋ฉ๋‹ˆ๋‹ค(๋ผˆ๊ฐ€ ์ •์ ์˜ ์›€์ง์ž„์„ ์ž์œจ์ ์œผ๋กœ ์ œ์–ดํ•จ).

 

๋ธ”๋ Œ๋”์—์„œ ์ƒ์„ฑ๋œ ๊ณจ๊ฒฉ ๊ตฌ์กฐ์˜ ์˜ˆ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

 

์šฐ๋ฆฌ๊ฐ€ ์œ„์—์„œ ๋ณธ ๊ฒƒ์€ ์‚ฌ์‹ค ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์•„ํ‹ฐ์ŠคํŠธ๋Š” ๊ณจ๊ฒฉ ๊ตฌ์กฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  ๊ฐ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์œ ํ˜•("walk","run","die" ๋“ฑ)์— ๋Œ€ํ•œ ํ‚ค ํ”„๋ ˆ์ž„ ์„ธํŠธ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

ํ‚ค ํ”„๋ ˆ์ž„์—๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ผ ์ž„๊ณ„์ ์— ์žˆ๋Š” ๋ชจ๋“  ๋ผˆ์˜ ๋ณ€ํ™˜์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”ฝ ์—”์ง„์€ ํ‚ค ํ”„๋ ˆ์ž„์˜ ๋ณ€ํ™˜ ์‚ฌ์ด๋ฅผ ๋ณด๊ฐ„ํ•˜์—ฌ ํ‚ค ํ”„๋ ˆ์ž„ ๊ฐ„์˜ ๋ถ€๋“œ๋Ÿฌ์šด ์›€์ง์ž„์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

 

๊ณจ๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์— ์‚ฌ์šฉ๋˜๋Š” ๊ณจ๊ฒฉ ๊ตฌ์กฐ๋Š” ์ข…์ข… ๊ณ„์ธต ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ skeleton์ด ์ž์‹/๋ถ€๋ชจ ๊ด€๊ณ„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ skeleton tree๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

root bone์„ ์ œ์™ธํ•œ ๋ชจ๋“  ๋ผˆ์—๋Š” ๋ถ€๋ชจ๊ฐ€ ํ•˜๋‚˜์”ฉ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ธ์ฒด์˜ ๊ฒฝ์šฐ ํŒ”, ๋‹ค๋ฆฌ, ์†๊ฐ€๋ฝ ๋ผˆ์™€ ๊ฐ™์€ ์ž์‹ ๋ผˆ๋ฅผ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ํ•˜์—ฌ ๋“ฑ๋ผˆ๋ฅผ root๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถ€๋ชจ์˜ ๋ผˆ๊ฐ€ ์›€์ง์ด๋ฉด ๋ชจ๋“  ์ž์‹ ๋ผˆ๋“ค๋„ ์›€์ง์ด์ง€๋งŒ, ์ž์‹์˜ ๋ผˆ๊ฐ€ ์›€์ง์ด๋ฉด ๋ถ€๋ชจ๋Š” ์›€์ง์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์šฐ๋ฆฌ์˜ ์†๊ฐ€๋ฝ์€ ์†์„ ์›€์ง์ด์ง€ ์•Š๊ณ ๋„ ์›€์ง์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ์†์ด ์›€์ง์ด๋ฉด ๋ชจ๋“  ์†๊ฐ€๋ฝ์ด ์›€์ง์ž…๋‹ˆ๋‹ค). ์‹ค์งˆ์ ์ธ ๊ด€์ ์—์„œ ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๋ผˆ์˜ ๋ณ€ํ˜•์„ ์ฒ˜๋ฆฌํ•  ๋•Œ ๊ทธ๊ฒƒ์„ ๊ทธ๊ฒƒ์œผ๋กœ๋ถ€ํ„ฐ root๋กœ ์ด๋„๋Š” ๋ชจ๋“  ๋ถ€๋ชจ ๋ผˆ์˜ ๋ณ€ํ˜•๊ณผ ๊ฒฐํ•ฉํ•  ํ•„์š”๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

๋” ์ด์ƒ ์กฐ์ž‘์— ๋Œ€ํ•ด ๋…ผ์˜ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ์˜์—ญ ๋ฐ–์— ์žˆ๋Š” ๋ณต์žกํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค. ๋ชจ๋ธ๋ง ์†Œํ”„ํŠธ์›จ์–ด๋Š” ์˜ˆ์ˆ ๊ฐ€๊ฐ€ ์ด ์ผ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๊ณ ๊ธ‰ ๋„๊ตฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ ๋‹น์‹ ์€ ๋ฉ‹์ง‘ mesh์™€ skeleton์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ํ›Œ๋ฅญํ•œ ์˜ˆ์ˆ ๊ฐ€๊ฐ€ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. skeletal ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ๊ทธ๋ž˜ํ”ฝ ์—”์ง„์ด ๋ฌด์—‡์„ ํ•ด์•ผ ํ•˜๋Š”์ง€ ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ฒซ ๋ฒˆ์žฌ ๋‹จ๊ณ„๋Š” ์ •์  ๋ฒ„ํผ๋ฅผ ์ •์ ๋ณ„ ๊ณจ๊ฒฉ ์ •๋ณด๋กœ ๋ณด๊ฐ•ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ช‡ ๊ฐ€์ง€ ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋ ค๋Š” ๊ฒƒ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

๊ฐ ๊ผญ์ง“์ ์— ๋Œ€ํ•ด ๊ฐ ์Šฌ๋กฏ์— ๊ณจ๊ฒฉ ID์™€ ๊ฐ€์ค‘์น˜๊ฐ€ ํฌํ•จ๋œ ์Šฌ๋กฏ ๋ฐฐ์—ด์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ์˜ ์‚ถ์„ ๋” ๋‹จ์ˆœํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์šฐ๋ฆฌ๋Š” 4๊ฐœ์˜ ์Šฌ๋กฏ์ด ์žˆ๋Š” ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ 4๊ฐœ ์ด์ƒ์˜ ๋ผˆ์— ์˜ํ•ด ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ •์ ์ด ์—†๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๊ณจ๊ฒฉ์ด ๋” ๋งŽ์€ ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜๋ ค๋ฉด ๋ฐฐ์—ด ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•˜์ง€๋งŒ ์ด ํŠœํ† ๋ฆฌ์–ผ ๋ฐ๋ชจ์— ํฌํ•จ๋œ Doom 3 ๋ชจ๋ธ์˜ ๊ฒฝ์šฐ ๊ณจ๊ฒฉ 4๊ฐœ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ์˜ ์ƒˆ๋กœ์šด ๊ผญ์ง“์  ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 

bone ID๋Š” bone ๋ณ€ํ™˜ ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ณ€ํ™˜์€ WVP ํ–‰๋ ฌ ์•ž์˜ ์œ„์น˜์™€ ์ •๊ทœ์— ์ ์šฉ๋ฉ๋‹ˆ๋‹ค(์ฆ‰, ์ •์ ์„ "bone space"์—์„œ ๋กœ์ปฌ ๊ณต๊ฐ„์œผ๋กœ ๋ณ€ํ™˜).

๊ฐ€์ค‘์น˜๋Š” ์—ฌ๋Ÿฌ ๋ผˆ์˜ ๋ณ€ํ™˜์„ ํ•˜๋‚˜์˜ ๋ณ€ํ™˜์œผ๋กœ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋ฉฐ, ์–ด๋–ค ๊ฒฝ์šฐ์—๋„ ์ด ๊ฐ€์ค‘์น˜๋Š” ์ •ํ™•ํžˆ 1(๋ชจ๋ธ๋ง ์†Œํ”„ํŠธ์›จ์–ด์˜ ์ฑ…์ž„)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ‚ค ํ”„๋ ˆ์ž„ ์‚ฌ์ด๋ฅผ ๋ณด๊ฐ„ํ•˜๊ณ  ๋ชจ๋“  ํ”„๋ ˆ์ž„์˜ ๊ณจ๊ฒฉ ๋ณ€ํ™˜ ๋ฐฐ์—ด์„ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

 

๋ผˆ ๋ณ€ํ˜•์˜ ๋ฐฐ์—ด์ด ๋งŒ๋“ค์–ด์ง€๋Š” ๋ฐฉ๋ฒ•์€ ๋Œ€๊ฐœ ๊นŒ๋‹ค๋กœ์šด ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

๋ณ€ํ™˜์€ ๊ณ„์ธต ๊ตฌ์กฐ(์ฆ‰, ํŠธ๋ฆฌ)๋กœ ์„ค์ •๋˜๋ฉฐ ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ•์€ ํŠธ๋ฆฌ์˜ ๋ชจ๋“  ๋…ธํŠธ์— ์Šค์ผ€์ผ๋ง ๋ฒกํ„ฐ, ํšŒ์ „ ์ฟผํ„ฐ ๋ฐ ๋ณ€ํ™˜ ๋ฒกํ„ฐ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ๊ฐ ๋…ธ๋“œ์—๋Š” ์ด๋Ÿฌํ•œ ํ•ญ๋ชฉ์˜ ๋ฐฐ์—ด์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐ์—ด์˜ ๋ชจ๋“  ํ•ญ๋ชฉ์—๋Š” ํƒ€์ž„์Šคํƒฌํ”„๊ฐ€ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์‹œ๊ฐ„์ด ํƒ€์ž„์Šคํƒฌํ”„ ์ค‘ ํ•˜๋‚˜์™€ ์ •ํ™•ํžˆ ์ผ์น˜ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋“œ๋ฌผ๊ธฐ ๋•Œ๋ฌธ์— ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์‹œ์ ์— ๋Œ€ํ•œ ์ •ํ™•ํ•œ ๋ณ€ํ™˜์„ ์–ป์œผ๋ ค๋ฉด ์ฝ”๋“œ๊ฐ€ ์Šค์ผ€์ผ๋ง/ํšŒ์ „/๋ฒˆ์—ญ์„ ๋ณด๊ฐ„ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ํ˜„์žฌ์˜ ๋ผˆ์—์„œ root๊นŒ์ง€ ๊ฐ ๋…ธ๋“œ์— ๋Œ€ํ•ด ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ด ๋ณ€ํ™˜ ์ฒด์ธ์„ ํ•จ๊ป˜ ๊ณฑํ•˜์—ฌ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. ๊ฐ ๊ณจ๊ฒฉ์— ๋Œ€ํ•ด ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ ๋‹ค์Œ ์‰์ด๋”๋ฅผ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.

 

์ง€๊ธˆ๊นŒ์ง€ ์šฐ๋ฆฌ๊ฐ€ ์ด์•ผ๊ธฐํ•œ ๋ชจ๋“  ๊ฒƒ์€ ๊ฝค ์ผ๋ฐ˜์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๊ฒƒ์€ Assimp์˜ ๊ณจ๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์— ๋Œ€ํ•œ ํŠœํ† ๋ฆฌ์–ผ ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋‹ค์‹œ ๋“ค์–ด๊ฐ€์„œ ์–ด๋–ป๊ฒŒ ์Šคํ‚ค๋‹์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณผ ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

Assimip์˜ ์ข‹์€ ์ ์€ ์—ฌ๋Ÿฌ ํ˜•์‹์˜ ๊ณจ๊ฒฉ ์ •๋ณด ๋กœ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚˜์œ์ ์€ ์‰์ด๋”์— ํ•„์š”ํ•œ ๊ณจ๊ฒฉ ๋ณ€ํ™˜์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์ƒ์„ฑ๋˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์— ๋Œ€ํ•ด ์—ฌ์ „ํžˆ ์ƒ๋‹นํ•œ ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ •์  ์ˆ˜์ค€์˜ ๋ผˆ ์ •๋ณด๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ Assimp ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์˜ ๊ด€๋ จ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค:

 

 

์•„๋งˆ Assimp์— ๋Œ€ํ•œ ํŠœํ† ๋ฆฌ์–ผ์—์„œ ๊ธฐ์–ตํ•˜์‹œ๊ฒ ์ง€๋งŒ, ๋ชจ๋“  ๊ฒƒ์ด aiScene ํด๋ž˜์Šค(๋งค์‰ฌ ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ ๋ฐ›๋Š” ๊ฐœ์ฒด)์— ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. aiScene์—๋Š” aiMesh ๊ฐœ์ฒด์˜ ๋ฐฐ์—ด์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. aiMesh๋Š” ๋ชจ๋ธ์˜ ์ผ๋ถ€์ด๋ฉฐ ์œ„์น˜, ์ •๊ทœ ํ…์Šค์ฒ˜ ์ขŒํ‘œ ๋“ฑ๊ณผ ๊ฐ™์€ ์ •์  ์ˆ˜์ค€์˜ ํ•ญ๋ชฉ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ aiMesh์—๋Š” aiBone ๊ฐ์ฒด์˜ ๋ฐฐ์—ด๋„ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๋†€๋ž„ ๊ฒƒ๋„ ์—†์ด, aiBone์€ mesh์˜ ๊ณจ๊ฒฉ์— ์žˆ๋Š” ํ•˜๋‚˜์˜ ๋ผˆ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ๊ฐ ๊ณจ๊ฒฉ์—๋Š” ๊ณจ๊ฒฉ ๊ณ„์ธต ๊ตฌ์กฐ(์•„๋ž˜ ์ฐธ์กฐ), ์ •์  ๊ฐ€์ค‘์น˜ ๋ฐฐ์—ด ๋ฐ 4x4 ์˜คํ”„์…‹ ํ–‰๋ ฌ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ์ด๋ฆ„์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ํ–‰๋ ฌ์ด ํ•„์š”ํ•œ ์ด์œ ๋Š” ์ •์ ์ด ์ผ๋ฐ˜์ ์ธ ๋กœ์ปฌ ๊ณต๊ฐ„์— ์ €์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๊ณจ๊ฒฉ ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ์ง€์›๋˜์ง€ ์•Š๋”๋ผ๋„ ๊ธฐ์กด ์ฝ”๋“œ ๊ธฐ๋ฐ˜์ด ๋ชจ๋ธ์„ ๋กœ๋“œํ•˜๊ณ  ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ณ„์ธต ๊ตฌ์กฐ์˜ ๋ผˆ ๋ณ€ํ™˜์€ ๋ผˆ ๊ณต๊ฐ„์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.(๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ๋ผˆ๋Š” ๊ณ ์œ ํ•œ ๊ณต๊ฐ„์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์šฐ๋ฆฌ๊ฐ€ ํ•จ๊ป˜ ๋ณ€ํ™˜์„ ๊ณฑํ•ด์•ผ ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค). ์˜คํ”„์…‹ ๋งคํŠธ๋ฆญ์Šค์˜ ์ž‘์—…์€ ๋งค์‰ฌ์˜ ๊ตญ์†Œ ๊ณต๊ฐ„์—์„œ ์ •์  ์œ„์น˜๋ฅผ ํŠน์ • ๋ผˆ์˜ ๊ณต๊ฐ„์œผ๋กœ ์ด๋™์‹œํ‚ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ •์  ๊ฐ€์ค‘์น˜ ๋ฐฐ์—ด์€ ์‚ฌ๋ฌผ๋“ค์ด ํฅ๋ฏธ๋กœ์›Œ์ง€๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ๊ณณ์ž…๋‹ˆ๋‹ค.

์ด ๋ฐฐ์—ด์˜ ๊ฐ ํ•ญ๋ชฉ์—๋Š” aiMesh์˜ ์ •์  ๋ฐฐ์—ด์— ๋Œ€ํ•œ ์ธ๋ฑ์Šค(๊ผญ์ง“์ ์ด ๋™์ผํ•œ ๊ธธ์ด๋ฅผ ๊ฐ€์ง„ ์—ฌ๋Ÿฌ ๋ฐฐ์—ด์— ๊ฑธ์ณ ๋ถ„์‚ฐ๋จ)์™€ ๊ฐ€์ค‘์น˜๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ผญ์ง“์  ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์€ 1์ด์–ด์•ผ ํ•˜์ง€๋งŒ ์ด๋ฅผ ์ฐพ์œผ๋ ค๋ฉด ๋ชจ๋“  ๋ผˆ๋ฅผ ํ†ต๊ณผํ•˜๊ณ  ๊ฐ ํŠน์ • ๊ผญ์ง“์ ์— ๋Œ€ํ•œ ์ผ์ข…์˜ ๋ชฉ๋ก์œผ๋กœ ๊ฐ€์ค‘์น˜๋ฅผ ๋ˆ„์ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ •์  ์ˆ˜์ค€์—์„œ ๊ณจ๊ฒฉ ์ •๋ณด๋ฅผ ๊ตฌ์ถ•ํ•œ ํ›„ ๊ณจ๊ฒฉ ๋ณ€ํ™˜ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‰์ด๋”์— ๋กœ๋“œํ•  ์ตœ์ข… ๋ณ€ํ™˜์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ทธ๋ฆผ์—๋Š” ๊ด€๋ จ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ํ‘œ์‹œ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค:

 

 

๋‹ค์‹œ, ์šฐ๋ฆฌ๋Š” aiScene์—์„œ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. aiScene ๊ฐœ์ฒด์—๋Š” ๋…ธ๋“œ ๊ณ„์ธต ๊ตฌ์กฐ(์ฆ‰, ํŠธ๋ฆฌ)์˜ ๋ฃจํŠธ์ธ aiNode ํด๋ž˜์Šค์˜ ๊ฐœ์ฒด์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋ฆฌ์˜ ๊ฐ ๋…ธ๋“œ์—๋Š” ๋ถ€๋ชจ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ์™€ ์ž์‹์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ ๋ฐฐ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ tree๋ฅผ ํŽธ๋ฆฌํ•˜๊ฒŒ ์™”๋‹ค๊ฐ”๋‹ค ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

๋˜ํ•œ ๋…ธ๋“œ๋Š” ๋…ธ๋“œ ๊ณต๊ฐ„์—์„œ ๋ถ€๋ชจ ๊ณต๊ฐ„์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๋ณ€ํ™˜ ํ–‰๋ ฌ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋…ธ๋“œ์— ์ด๋ฆ„์ด ์žˆ์„ ์ˆ˜๋„ ์žˆ๊ณ  ์—†์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋…ธ๋“œ๊ฐ€ ๊ณ„์ธต์—์„œ ๊ณจ๊ฒฉ์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒฝ์šฐ ๋…ธ๋“œ ์ด๋ฆ„์ด ๊ณจ๊ฒฉ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋…ธ๋“œ์— ์ด๋ฆ„์ด ์—†๋Š” ๊ฒฝ์šฐ(์ฆ‰, ๋Œ€์‘ํ•˜๋Š” ๊ณจ๊ฒฉ์ด ์—†์Œ) ๋…ธ๋“œ์˜ ์—ญํ• ์€ ๋‹จ์ˆœํžˆ ๋ชจ๋ธ์„ ๋ถ„ํ•ดํ•˜๊ณ  ์ค‘๊ฐ„ ๋ณ€ํ™˜์„ ๋ฐฐ์น˜ํ•˜๋Š” ๊ฒƒ์„ ๋•๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ํผ์ฆ์˜ ๋งˆ์ง€๋ง‰ ์กฐ๊ฐ์€ aiScene ๊ฐ์ฒด์—๋„ ์ €์žฅ๋œ aiAnimation ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ๋‹จ์ผ aiAnimation ๊ฐ์ฒด๋Š” "walk", "run", "shoot" ๋“ฑ๊ณผ ๊ฐ™์€ ์ผ๋ จ์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํ”„๋ ˆ์ž„์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. ํ”„๋ ˆ์ž„ ์‚ฌ์ด๋ฅผ ๋ณด๊ฐ„ํ•จ์œผ๋กœ์จ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฆ„๊ณผ ์ผ์น˜ํ•˜๋Š” ์›ํ•˜๋Š” ์‹œ๊ฐ์  ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜์—๋Š” ๋ˆˆ๊ธˆ์˜ ์ง€์† ์‹œ๊ฐ„๊ณผ ์ดˆ๋‹น ๋ˆˆ๊ธˆ ์ˆ˜(์˜ˆ: 100๊ฐœ์˜ ๋ˆˆ๊ธˆ๊ณผ 25๊ฐœ์˜ ๋ˆˆ๊ธˆ์€ 4์ดˆ์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋‚˜ํƒ€๋ƒ„)๊ฐ€ ์žˆ์–ด ์• ๋‹ˆ๋ฉ”์ด์…˜์ด ๋ชจ๋“  ํ•˜๋“œ์›จ์–ด์—์„œ ๋™์ผํ•˜๊ฒŒ ๋ณด์ด๋„๋ก ์ง„ํ–‰ ์‹œ๊ฐ„์„ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด ์• ๋‹ˆ๋ฉ”์ด์…˜์—๋Š” ์ฑ„๋„์ด๋ผ๊ณ  ํ•˜๋Š” aiNodeAnim ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์ฑ„๋„์€ ์‚ฌ์‹ค ๋ชจ๋“  ๋ณ€ํ˜•์ด ์žˆ๋Š” ๋ผˆ์ž…๋‹ˆ๋‹ค. ์ฑ„๋„์—๋Š” ๊ณ„์ธต ๊ตฌ์กฐ์˜ ๋…ธ๋“œ ์ค‘ ํ•˜๋‚˜์™€ ์„ธ ๊ฐœ์˜ ๋ณ€ํ™˜ ๋ฐฐ์—ด๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•˜๋Š” ์ด๋ฆ„์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํŠน์ • ์‹œ์ ์˜ ์ตœ์ข… ๋ผˆ ๋ณ€ํ™˜์„ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ด ์„ธ ๋ฐฐ์—ด์—์„œ ๊ฐ๊ฐ ์‹œ๊ฐ„๊ณผ ์ผ์น˜ํ•˜๋Š” ๋‘ ๊ฐœ์˜ ํ•ญ๋ชฉ์„ ์ฐพ๊ณ  ๊ทธ ์‚ฌ์ด๋ฅผ ๋ณด๊ฐ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ณ€ํ™˜์„ ํ•˜๋‚˜์˜ ํ–‰๋ ฌ๋กœ ๊ฒฐํ•ฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ ํ›„์—๋Š” ๊ณ„์ธต ๊ตฌ์กฐ์—์„œ ํ•ด๋‹น ๋…ธ๋“œ๋ฅผ ์ฐพ์•„ ์ƒ์œ„ ๋…ธ๋“œ๋กœ ์ด๋™ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ถ€๋ชจ์— ํ•ด๋‹นํ•˜๋Š” ์ฑ„๋„์ด ํ•„์š”ํ•˜๊ณ  ๋™์ผํ•œ ๋ณด๊ฐ„ ๊ณผ์ •์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋‘ ๋ณ€ํ™˜์„ ํ•จ๊ป˜ ๊ณฑํ•˜๊ณ  ๊ณ„์ธต์˜ root์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๊ณ„์†ํ•ฉ๋‹ˆ๋‹ค.

Source Walthru

(mesh.cpp:75)

bool Mesh::LoadMesh(const string& Filename)
{
    // Release the previously loaded mesh (if it exists)
    Clear();

    // Create the VAO
    glGenVertexArrays(1, &m_VAO);
    glBindVertexArray(m_VAO);

    // Create the buffers for the vertices attributes
    glGenBuffers(ARRAY_SIZE_IN_ELEMENTS(m_Buffers), m_Buffers);

    bool Ret = false;

    m_pScene = m_Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals |
                                    aiProcess_FlipUVs);

    if (m_pScene) {
       m_GlobalInverseTransform = m_pScene->mRootNode->mTransformation;
       m_GlobalInverseTransform = m_GlobalInverseTransform.Inverse();
       Ret = InitFromScene(m_pScene, Filename);
    }
    else {
       printf("Error parsing '%s': '%s'\n", Filename.c_str(), m_Importer.GetErrorString());
    }

    // Make sure the VAO is not changed from the outside
    glBindVertexArray(0);

    return Ret;
}

๋‹ค์Œ์€ ๋งค์‰ฌ ํด๋ž˜์Šค์˜ ์—…๋ฐ์ดํŠธ๋œ ์ง„์ž…์ ์œผ๋กœ, ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ๊ตต์€ ๊ธ€์”จ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ฃผ๋ชฉํ•ด์•ผ ํ•  ๋ช‡ ๊ฐ€์ง€ ๋ณ€ํ™”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜๋Š” ์ž„ํฌํ„ฐ์™€ aiScene ๊ฐœ์ฒด๊ฐ€ ์ด์ œ ๋ณ€์ˆ˜๋ฅผ ์Œ“์ง€ ์•Š๊ณ  ํด๋ž˜์Šค ๋ฉค๋ฒ„๊ฐ€ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š” ๋Ÿฐํƒ€์ž„ ์ค‘์— ์šฐ๋ฆฌ๋Š” aiScene ๊ฐ์ฒด๋กœ ๋‹ค์‹œ ๋Œ์•„๊ฐˆ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ˆ˜์ž…์ž์™€ ์žฅ๋ฉด์˜ ๋ฒ”์œ„๋ฅผ ๋ชจ๋‘ ํ™•์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ๊ฒŒ์ž„์—์„œ๋Š” ํ•„์š”ํ•œ ๊ฒƒ์„ ๋ณต์‚ฌํ•˜์—ฌ ์ตœ์ ํ™”๋œ ํ˜•์‹์œผ๋กœ ์ €์žฅํ•˜๊ณ  ์‹ถ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ต์œก์ ์ธ ๋ชฉ์ ์„ ์œ„ํ•ด์„œ๋Š” ์ด๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

 

๋‘ ๋ฒˆ์งธ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ๊ณ„์ธต ๊ตฌ์กฐ์˜ ๋ฃจํŠธ์— ๋Œ€ํ•œ ๋ณ€ํ™˜ ํ–‰๋ ฌ์ด ์ถ”์ถœ๋˜๊ณ  ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ์ €์žฅ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์•ž์œผ๋กœ ๋” ๋ฉ€๋ฆฌ์„œ ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ–‰๋ ฌ ์—ญ์ฝ”๋“œ๊ฐ€ Assimp ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ Matrix4f ํด๋ž˜์Šค๋กœ ๋ณต์‚ฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

(mesh.h:69)

struct VertexBoneData
{
    uint IDs[NUM_BONES_PER_VERTEX];
    float Weights[NUM_BONES_PER_VERTEX];
}

(mesh.cpp:107)

bool Mesh::InitFromScene(const aiScene* pScene, const string& Filename)
{
    ...
    vector<VertexBoneData> Bones;
    ...
    Bones.resize(NumVertices);
    ...
    glBindBuffer(GL_ARRAY_BUFFER, m_Buffers[BONE_VB]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Bones[0]) * Bones.size(), &Bones[0], GL_STATIC_DRAW);
    glEnableVertexAttribArray(BONE_ID_LOCATION);
    glVertexAttribIPointer(BONE_ID_LOCATION, 4, GL_INT, sizeof(VertexBoneData), (const GLvoid*)0);
    glEnableVertexAttribArray(BONE_WEIGHT_LOCATION);
    glVertexAttribPointer(BONE_WEIGHT_LOCATION, 4, GL_FLOAT, GL_FALSE, sizeof(VertexBoneData), (const GLvoid*)16);
    ...
}

์œ„์˜ ๊ตฌ์กฐ๋Š” ๊ผญ์ง“์  ์ˆ˜์ค€์—์„œ ์šฐ๋ฆฌ๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ์„ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ 4๊ฐœ์˜ ๋ผˆ(๋ผˆ๋‹น ID ๋ฐ ๋ฌด๊ฒŒ)๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์ถฉ๋ถ„ํ•œ ์ €์žฅ ๊ณต๊ฐ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.

VertexBoneData๋Š” ์‰์ด๋”์— ์‰ฝ๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ทธ๋ ‡๊ฒŒ ๊ตฌ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์œ„์น˜ 0, 1, 2์— ๊ฐ๊ฐ ์œ„์น˜, ํ…์Šค์ฒ˜ ์ขŒํ‘œ ๋ฐ ์ผ๋ฐ˜ ๊ฒฝ๊ณ„๋ฅผ ํ™•๋ณดํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์น˜ 3์—์„œ ๊ณจ๊ฒฉ ID๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๊ณ  ์œ„์น˜ 4์—์„œ ๊ฐ€์ค‘์น˜๋ฅผ ๋ฐ”์ธ๋”ฉํ•˜๋„๋ก VAO๋ฅผ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ glVertexAttribute๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์ฃผ๋ชฉํ•˜๋Š” ๊ฒƒ๋„ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ID๋ฅผ ๋ฐ”์ธ๋”ฉํ•  glVertexAttributePointer๊ฐ€ ์•„๋‹Œ IPointer์ž…๋‹ˆ๋‹ค. ์ด ์ ์— ์ฃผ์˜ํ•˜์‹ญ์‹œ์˜ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์‰์ด๋”์— ์†์ƒ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 

(mesh.cpp:213)

void Mesh::LoadBones(uint MeshIndex, const aiMesh* pMesh, vector& Bones)
{
    for (uint i = 0 ; i < pMesh->mNumBones ; i++) {
        uint BoneIndex = 0;
        string BoneName(pMesh->mBones[i]->mName.data);

        if (m_BoneMapping.find(BoneName) == m_BoneMapping.end()) {
            BoneIndex = m_NumBones;
            m_NumBones++;
            BoneInfo bi;
            m_BoneInfo.push_back(bi);
        }
        else {
            BoneIndex = m_BoneMapping[BoneName];
        }

        m_BoneMapping[BoneName] = BoneIndex;
        m_BoneInfo[BoneIndex].BoneOffset = pMesh->mBones[i]->mOffsetMatrix;

        for (uint j = 0 ; j < pMesh->mBones[i]->mNumWeights ; j++) {
            uint VertexID = m_Entries[MeshIndex].BaseVertex + pMesh->mBones[i]->mWeights[j].mVertexId;
            float Weight = pMesh->mBones[i]->mWeights[j].mWeight;
            Bones[VertexID].AddBoneData(BoneIndex, Weight);
        }
    }
}

์œ„์˜ ํ•จ์ˆ˜๋Š” ๋‹จ์ผ aiMesh ๊ฐœ์ฒด์— ๋Œ€ํ•œ ์ •์  ๊ณจ๊ฒฉ ์ •๋ณด๋ฅผ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. Mesh::InitMesh()์—์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” VertexBoneData ๊ตฌ์กฐ๋ฅผ ์ฑ„์šฐ๋Š” ๊ฒƒ ์™ธ์—๋„ ๊ณจ๊ฒฉ ์ด๋ฆ„๊ณผ ๊ณจ๊ฒฉ ID(์ด ํ•จ์ˆ˜์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋Š” ์‹คํ–‰์ค‘์ธ ์ธ๋ฑ์Šค) ์‚ฌ์ด์˜ ๋งต์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๊ณจ๊ฒฉ ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฒกํ„ฐ์— ์˜คํ”„์…‹ ํ–‰๋ ฌ์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ์ •์  ID๊ฐ€ ๊ณ„์‚ฐ๋˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค. ์ •์  ID๋Š” ๋‹จ์ผ ๋งค์‰ฌ์™€ ๊ด€๋ จ์ด ์žˆ๊ณ  ๋ชจ๋“  ๋งค์‰ฌ๋ฅผ ๋‹จ์ผ ๋ฒกํ„ฐ์— ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ aiMesh์˜ ๊ธฐ๋ณธ ์ •์  ID๋ฅผ mWeights ๋ฐฐ์—ด์˜ ์ •์  ID์— ์ถ”๊ฐ€ํ•˜์—ฌ ์ ˆ๋Œ€ ์ •์  ID๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

 

(mesh.cpp:29)

void Mesh::VertexBoneData::AddBoneData(uint BoneID, float Weight)
{
    for (uint i = 0 ; i < ARRAY_SIZE_IN_ELEMENTS(IDs) ; i++) {
        if (Weights[i] == 0.0) {
            IDs[i] = BoneID;
            Weights[i] = Weight;
            return;
        }
    }

    // should never get here - more bones than we have space for
    assert(0);
}

์ด ์œ ํ‹ธ๋ฆฌํ‹ฐ ํ•จ์ˆ˜๋Š” VertexBoneData ๊ตฌ์กฐ์—์„œ ๋นˆ ์Šฌ๋กฏ์„ ์ฐพ์•„ ๊ณจ๊ฒฉ ID์™€ ๊ฐ€์ค‘์น˜๋ฅผ ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ถ€ ์ •์ ์€ 4๊ฐœ ๋ฏธ๋งŒ์˜ ๋ผˆ์— ์˜ํ•ด ์˜ํ–ฅ์„ ๋ฐ›์ง€๋งŒ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๋ผˆ์˜ ๋ฌด๊ฒŒ๊ฐ€ 0์œผ๋กœ ์œ ์ง€๋˜๊ธฐ ๋•Œ๋ฌธ์—(VertexBoneData ์ƒ์„ฑ์ž ์ฐธ์กฐ), ์ด๋Š” ๋ชจ๋“  ๋ผˆ ์ˆ˜์— ๋Œ€ํ•ด ๋™์ผํ•œ ๊ฐ€์ค‘์น˜ ๊ณ„์‚ฐ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 (mesh.cpp:473)

Matrix4f Mesh::BoneTransform(float TimeInSeconds, vector<Matrix4f>& Transforms)
{
    Matrix4f Identity;
    Identity.InitIdentity();

    float TicksPerSecond = m_pScene->mAnimations[0]->mTicksPerSecond != 0 ?
                            m_pScene->mAnimations[0]->mTicksPerSecond : 25.0f;
    float TimeInTicks = TimeInSeconds * TicksPerSecond;
    float AnimationTime = fmod(TimeInTicks, m_pScene->mAnimations[0]->mDuration);

    ReadNodeHierarchy(AnimationTime, m_pScene->mRootNode, Identity);

    Transforms.resize(m_NumBones);

    for (uint i = 0 ; i < m_NumBones ; i++) {
        Transforms[i] = m_BoneInfo[i].FinalTransformation;
    }
}

์•ž์„œ ๋ณธ ์ •์  ์ˆ˜์ค€์˜ ๊ณจ๊ฒฉ ์ •๋ณด ๋กœ๋“œ๋Š” ๋งค์‰ฌ๊ฐ€ ์‹œ์ž‘ ์ค‘์— ๋กœ๋“œ๋  ๋•Œ ํ•œ ๋ฒˆ๋งŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด์ œ ์šฐ๋ฆฌ๋Š” ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์‰์ด๋”์— ๋“ค์–ด๊ฐ€๋Š” ๋ผˆ ๋ณ€ํ˜•์„ ๊ณ„์‚ฐํ•˜๋Š” ๋‘ ๋ฒˆ์žฌ ๋ถ€๋ถ„์œผ๋กœ ๋„˜์–ด๊ฐ‘๋‹ˆ๋‹ค. ์œ„์˜ ๊ธฐ๋Šฅ์€ ์ด ํ™œ๋™์˜ ์‹œ์ž‘์ ์ž…๋‹ˆ๋‹ค. ํ˜ธ์ถœ์ž๋Š” ํ˜„์žฌ ์‹œ๊ฐ„์„ ์ดˆ ๋‹จ์œ„๋กœ ๋ณด๊ณ ํ•˜๊ณ (๋ถ„์ˆ˜์ผ ์ˆ˜ ์žˆ์Œ), ์—…๋ฐ์ดํŠธํ•ด์•ผํ•˜๋Š” ํ–‰๋ ฌ์˜ ๋ฒกํ„ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ฃผ๊ธฐ ๋‚ด์—์„œ ์ƒ๋Œ€์ ์ธ ์‹œ๊ฐ„์„ ์ฐพ๊ณ  ๋…ธ๋“œ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ๋Š” ํ˜ธ์ถœ์ž์—๊ฒŒ ๋ฐ˜ํ™˜๋˜๋Š” ์ผ๋ จ์˜ ๋ณ€ํ™˜์ž…๋‹ˆ๋‹ค.

 

(mesh.cpp:428)

void Mesh::ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const Matrix4f& ParentTransform)
{
    string NodeName(pNode->mName.data);

    const aiAnimation* pAnimation = m_pScene->mAnimations[0];

    Matrix4f NodeTransformation(pNode->mTransformation);

    const aiNodeAnim* pNodeAnim = FindNodeAnim(pAnimation, NodeName);

    if (pNodeAnim) {
        // Interpolate scaling and generate scaling transformation matrix
        aiVector3D Scaling;
        CalcInterpolatedScaling(Scaling, AnimationTime, pNodeAnim);
        Matrix4f ScalingM;
        ScalingM.InitScaleTransform(Scaling.x, Scaling.y, Scaling.z);

        // Interpolate rotation and generate rotation transformation matrix
        aiQuaternion RotationQ;
        CalcInterpolatedRotation(RotationQ, AnimationTime, pNodeAnim);
        Matrix4f RotationM = Matrix4f(RotationQ.GetMatrix());

        // Interpolate translation and generate translation transformation matrix
        aiVector3D Translation;
        CalcInterpolatedPosition(Translation, AnimationTime, pNodeAnim);
        Matrix4f TranslationM;
        TranslationM.InitTranslationTransform(Translation.x, Translation.y, Translation.z);

        // Combine the above transformations
        NodeTransformation = TranslationM * RotationM * ScalingM;
    }

    Matrix4f GlobalTransformation = ParentTransform * NodeTransformation;

    if (m_BoneMapping.find(NodeName) != m_BoneMapping.end()) {
        uint BoneIndex = m_BoneMapping[NodeName];
        m_BoneInfo[BoneIndex].FinalTransformation = m_GlobalInverseTransform * GlobalTransformation *
                                                    m_BoneInfo[BoneIndex].BoneOffset;
    }

    for (uint i = 0 ; i < pNode->mNumChildren ; i++) {
        ReadNodeHierarchy(AnimationTime, pNode->mChildren[i], GlobalTransformation);
    }
}

์ด ํ•จ์ˆ˜๋Š” ๋…ธ๋“œ ํŠธ๋ฆฌ๋ฅผ ํ†ต๊ณผํ•˜๊ณ  ์ง€์ •๋œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๊ฐ ๋…ธ๋“œ/๋ณธ์— ๋Œ€ํ•œ ์ตœ์ข… ๋ณ€ํ™˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋งค์‰ฌ๊ฐ€ ํ•˜๋‚˜์˜ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œํ€€์Šค๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค๋Š” ์ ์—์„œ ์ œํ•œ์ ์ž…๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ง€์›ํ•˜๋ ค๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ด๋ฆ„์„ ๋งํ•˜๊ณ  m_pScene->mAnimations[] ๋ฐฐ์—ด์—์„œ ๊ฒ€์ƒ‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ„์˜ ์ฝ”๋“œ๋Š” ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋ฐ๋ชจ ๋งค์‰ฌ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

 

๋…ธ๋“œ ๋ณ€ํ™˜์€ ๋…ธ๋“œ์˜ mTransformation ๋ฉค๋ฒ„์—์„œ ์ดˆ๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๋…ธ๋“œ๊ฐ€ ๋ผˆ์™€ ์ผ์น˜ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ๊ทธ๊ฒƒ์ด ๋ผˆ์˜ ์ตœ์ข…๋ณ€ํ™˜์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๋˜๋ฉด ์ƒ์„ฑํ•œ ํ–‰๋ ฌ๋กœ ๋ฎ์–ด์”๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ๋จผ์ € ์• ๋‹ˆ๋ฉ”์ด์…˜์˜ ์ฑ„๋„ ๋ฐฐ์—ด์—์„œ ๋…ธ๋“œ ์ด๋ฆ„์„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์Šค์ผ€์ผ๋ง ๋ฒกํ„ฐ, ํšŒ์ „ ์ฟผํ„ฐ ๋ฐ ๋ณ€ํ™˜ ๋ฒกํ„ฐ๋ฅผ ๋ณด๊ฐ„ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ๋“ค์„ ํ•˜๋‚˜์˜ ํ–‰๋ ฌ๋กœ ๊ฒฐํ•ฉํ•˜๊ณ  ๋งค๊ฐœ ๋ณ€์ˆ˜๋กœ ์–ป์€ ํ–‰๋ ฌ(GlobablTransformation)๋กœ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.

์ด ํ•จ์ˆ˜๋Š” ์žฌ๊ท€์ ์ด๋ฉฐ ๊ธ€๋กœ๋ฒŒ ๋ณ€ํ™˜ ๋งค๊ฐœ ๋ณ€์ˆ˜๊ฐ€ ID ๋งคํŠธ๋ฆญ์Šค์ธ root ๋…ธ๋“œ์— ๋Œ€ํ•ด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ๊ฐ ๋…ธ๋“œ๋Š” ๋ชจ๋“  ์ž์‹์— ๋Œ€ํ•ด ์ด ํ•จ์ˆ˜๋ฅผ ์žฌ๊ท€์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ณ  ์ž์ฒด ๋ณ€ํ™˜์„ ์ „์—ญ ๋ณ€ํ™˜์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ์ฒ˜์Œ๋ถ€ํ„ฐ ๋๊นŒ์ง€ ๋ชจ๋“  ๋…ธ๋“œ์—์„œ ํ†ตํ•ฉ๋œ ๋ณ€ํ™˜ ์ฒด์ž„์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

m_BoneMapping ๋ฐฐ์—ด์€ ๋…ธ๋“œ ์ด๋ฆ„์„ ์ƒ์„ฑํ•˜๋Š” ์ธ๋ฑ์Šค์— ๋งคํ•‘ํ•˜๊ณ  ์ด ์ธ๋ฑ์Šค๋ฅผ ์ตœ์ข… ๋ณ€ํ™˜์ด ์ €์žฅ๋˜๋Š” m_BoneInfo ๋ฐฐ์—ด์˜ ํ•ญ๋ชฉ์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ตœ์ข… ๋ณ€ํ™˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋กœ์ปฌ ๊ณต๊ฐ„ ์œ„์น˜์—์„œ ์ •์ ์„ ๋…ธ๋“œ ๊ณต๊ฐ„์œผ๋กœ ๊ฐ€์ ธ์˜ค๋Š” ๋…ธ๋“œ ์˜คํ”„์…‹ ํ–‰๋ ฌ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ชจ๋“  ๋…ธ๋“œ ๋ถ€๋ชจ์˜ ๊ฒฐํ•ฉ๋œ ๋ณ€ํ™˜๊ณผ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„์— ๋”ฐ๋ผ ๋…ธ๋“œ์— ๋Œ€ํ•ด ๊ณ„์‚ฐํ•œ ํŠน์ • ๋ณ€ํ™˜์„ ๊ณฑํ•ฉ๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ๋Š” Assimp ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ•™ ๋ฌธ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์šฐ๋ฆฌ๋งŒ์˜ ์ฝ”๋“œ ๋ฒ ์ด์Šค๋กœ ๋ณต์ œํ•˜๋Š” ๊ฒƒ์ด ์˜๋ฏธ๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ด์„œ ๊ทธ๋ƒฅ Assimp๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

 

(mesh.cpp:387)

void Mesh::CalcInterpolatedRotation(aiQuaternion& Out, float AnimationTime, const aiNodeAnim* pNodeAnim)
{
    // we need at least two values to interpolate...
    if (pNodeAnim->mNumRotationKeys == 1) {
        Out = pNodeAnim->mRotationKeys[0].mValue;
        return;
    }

    uint RotationIndex = FindRotation(AnimationTime, pNodeAnim);
    uint NextRotationIndex = (RotationIndex + 1);
    assert(NextRotationIndex < pNodeAnim->mNumRotationKeys);
    float DeltaTime = pNodeAnim->mRotationKeys[NextRotationIndex].mTime - pNodeAnim->mRotationKeys[RotationIndex].mTime;
    float Factor = (AnimationTime - (float)pNodeAnim->mRotationKeys[RotationIndex].mTime) / DeltaTime;
    assert(Factor >= 0.0f && Factor <= 1.0f);
    const aiQuaternion& StartRotationQ = pNodeAnim->mRotationKeys[RotationIndex].mValue;
    const aiQuaternion& EndRotationQ = pNodeAnim->mRotationKeys[NextRotationIndex].mValue;
    aiQuaternion::Interpolate(Out, StartRotationQ, EndRotationQ, Factor);
    Out = Out.Normalize();
}

์ด ๋ฐฉ๋ฒ•์€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ์ง€์ •๋œ ์ฑ„๋„์˜ ํšŒ์ „์ฟผํ„ฐ๋ฅผ ๋ณด๊ฐ„ํ•ฉ๋‹ˆ๋‹ค(์ฑ„๋„์— ํ‚ค ์ฟผํ„ฐ ๋ฐฐ์—ด์ด ํฌํ•จ๋˜์–ด ์žˆ์Œ). ๋จผ์ € ํ•„์š”ํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„ ์ง์ „์˜ ํ•ต์‹ฌ ์ฟผํ„ฐ์˜ ์ธ๋ฑ์Šค๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„์—์„œ ์ด์ „ ํ‚ค๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ์™€ ํ•ด๋‹น ํ‚ค์™€ ๋‹ค์Œ ํ‚ค ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ ์‚ฌ์ด์˜ ๋น„์œจ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๊ทธ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋‘ ํ‚ค ์‚ฌ์ด๋ฅผ ๋ณด๊ฐ„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” Assimp ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด๊ฐ„์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์ •๊ทœํ™”ํ•ฉ๋‹ˆ๋‹ค. ์œ„์น˜ ๋ฐ ์Šค์ผ€์ผ๋ง์— ๋Œ€ํ•œ ํ•ด๋‹น ๋ฐฉ๋ฒ•์€ ๋งค์šฐ ์œ ์‚ฌํ•˜๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ๋Š” ์ธ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

(mesh.cpp:335)

uint Mesh::FindRotation(float AnimationTime, const aiNodeAnim* pNodeAnim)
{
    assert(pNodeAnim->mNumRotationKeys > 0);

    for (uint i = 0 ; i < pNodeAnim->mNumRotationKeys - 1 ; i++) {
        if (AnimationTime < (float)pNodeAnim->mRotationKeys[i + 1].mTime) {
            return i;
        }
    }

    assert(0);
}

์ด ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฐฉ๋ฒ•์€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„ ์ง์ „์˜ ํ‚ค ํšŒ์ „์„ ์ฐพ์Šต๋‹ˆ๋‹ค. N ํ‚ค ํšŒ์ „์ด ์žˆ์œผ๋ฉด ๊ฒฐ๊ณผ๋Š” 0์—์„œ N-2๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์• ๋‹ˆ๋ฉ”์ด์…˜ ์‹œ๊ฐ„์€ ํ•ญ์ƒ ์ฑ„๋„์˜ ์ง€์† ์‹œ๊ฐ„ ๋‚ด์— ํฌํ•จ๋˜๋ฏ€๋กœ ๋งˆ์ง€๋ง‰ ํ‚ค(N-1)๋Š” ์œ ํšจํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

(skihnning.vs)

#version 330

layout (location = 0) in vec3 Position;
layout (location = 1) in vec2 TexCoord;
layout (location = 2) in vec3 Normal;
layout (location = 3) in ivec4 BoneIDs;
layout (location = 4) in vec4 Weights;

out vec2 TexCoord0;
out vec3 Normal0;
out vec3 WorldPos0;

const int MAX_BONES = 200;

uniform mat4 gWVP;
uniform mat4 gWorld;
uniform mat4 gBones[MAX_BONES];

void main()
{
    mat4 BoneTransform = gBones[BoneIDs[0]] * Weights[0];
    BoneTransform += gBones[BoneIDs[1]] * Weights[1];
    BoneTransform += gBones[BoneIDs[2]] * Weights[2];
    BoneTransform += gBones[BoneIDs[3]] * Weights[3];

    vec4 PosL = BoneTransform * vec4(Position, 1.0);
    gl_Position = gWVP * PosL;
    TexCoord0 = TexCoord;
    vec4 NormalL = BoneTransform * vec4(Normal, 0.0);
    Normal0 = (gWorld * NormalL).xyz;
    WorldPos0 = (gWorld * PosL).xyz;
}

์ด์ œ ๋งค์‰ฌ ํด๋ž˜์Šค์˜ ๋ณ€๊ฒฝ ์ž‘์—…์„ ๋งˆ์ณค์œผ๋ฏ€๋กœ ์‰์ด๋” ์ˆ˜์ค€์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•  ์ž‘์—…์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € VSInput ๊ตฌ์กฐ์— ๊ณจ๊ฒฉ ID ๋ฐ ๊ฐ€์ค‘์น˜ ๋ฐฐ์—ด์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ, ๊ณจ๊ฒฉ ๋ณ€ํ™˜์„ ํฌํ•จํ•˜๋Š” ์ƒˆ๋กœ์šด ๊ท ์ผ ๋ฐฐ์—ด์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์‰์ด๋” ์ž์ฒด์—์„œ ์šฐ๋ฆฌ๋Š” ์ •์ ์˜ ๋ผˆ ๋ณ€ํ™˜ ํ–‰๋ ฌ๊ณผ ๊ฐ€์ค‘์น˜์˜ ์กฐํ•ฉ์œผ๋กœ ์ตœ์ข… ๋ผˆ ๋ณ€ํ™˜์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ์ตœ์ข… ํ–‰๋ ฌ์€ ์œ„์น˜์™€ ๋…ธ๋ง์„ ๊ณจ๊ฒฉ ๊ณต๊ฐ„์—์„œ ๋กœ์ปฌ ๊ณต๊ฐ„์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ถ€ํ„ฐ ๋ชจ๋“  ๊ฒƒ์ด ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

 

(tutorial38.cpp:140)

float RunningTime = (float)((double)GetCurrentTimeMillis() - (double)m_startTime) / 1000.0f;

m_mesh.BoneTransform(RunningTime, Transforms);

for (uint i = 0 ; i < Transforms.size() ; i++) {
    m_pEffect->SetBoneTransform(i, Transforms[i]);
}

์šฐ๋ฆฌ๊ฐ€ ๋งˆ์ง€๋ง‰์œผ๋กœ ํ•ด์•ผ ํ•  ์ผ์€ ์ด ๋ชจ๋“  ๊ฒƒ๋“ค์„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์— ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ž‘์—…์€ ์œ„์˜ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ์œ„์˜ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

GetCurrentTimeMillis() ํ•จ์ˆ˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ์‹œ์ž‘ ์ดํ›„์˜ ์‹œ๊ฐ„์„ ๋ฐ€๋ฆฌ์ดˆ ๋‹จ์œ„๋กœ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค(๋ถ„์ˆ˜๋ฅผ ์ˆ˜์šฉํ•˜๋ ค๋ฉด ๋ถ€๋™ ์†Œ์ˆ˜์ ์„ ์ฐธ๊ณ ํ•˜์‹ญ์‹œ์˜ค).

 

๋ชจ๋“  ์ž‘์—…์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•œ ๊ฒฝ์šฐ ์ตœ์ข… ๊ฒฐ๊ณผ๋Š” ์ด๊ฒƒ๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

 

์†Œ์Šค ์ฝ”๋“œ ์ฃผ์†Œ : https://github.com/emeiri/ogldev/tree/master/tutorial28_youtube

๋ฐ˜์‘ํ˜•

'๊ณต๋ถ€ > OpenGL ์ž๋ฃŒ ๋ฒˆ์—ญ' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[๋ฒˆ์—ญ] Tutorial 16 : Shadow mapping  (0) 2023.04.23
728x90

์›๋ณธ : http://www.opengl-tutorial.org/kr/intermediate-tutorials/tutorial-16-shadow-mapping/

 

ํŠœํ† ๋ฆฌ์–ผ 15์—์„œ๋Š” ์ •์  ์กฐ๋ช…์„ ํฌํ•จํ•˜๋Š” ๋ผ์ดํŠธ ๋งต์„ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

์•„์ฃผ ๋ฉ‹์ง„ ๊ทธ๋ฆผ์ž๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ์• ๋‹ˆ๋ฉ”์ด์…˜ ๋ชจ๋ธ์€ ๋‹ค๋ฃจ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

Shadow Map์€ ํ˜„์žฌ(2016๋…„ ๊ธฐ์ค€) ๋™์  Shadow๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์˜ ์ข‹์€ ์ ์€ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ธฐ์— ๊ฝค ์‰ฝ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚˜์œ์ ์€ ์ œ๋Œ€๋กœ ์ž‘์—… ํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์–ด๋ ต๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋จผ์ € ๊ธฐ๋ณธ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์†Œ๊ฐœํ•˜๊ณ  ๋‹จ์ ์„ ํ™•์ธํ•œ ๋‹ค์Œ ๋ช‡ ๊ฐ€์ง€ ๊ธฐ์ˆ ์„ ๊ตฌํ˜„ํ•˜์—ฌ ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Shadow Map์„ ์ž‘์„ฑํ•  ๋‹น์‹œ(2012๋…„)์—๋Š” ์—ฌ์ „ํžˆ ๋งŽ์€ ์—ฐ๊ตฌ๊ฐ€ ์ง„ํ–‰ ์ค‘์ธ ์ฃผ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์— ํ•„์š”์— ๋”ฐ๋ผ ์ž์ฒด Shadow Map์„ ๋”์šฑ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๊ธฐ๋ณธ Shadowmap

๊ธฐ๋ณธ Shadow Map ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‘ ๊ฐœ์˜ ํŒจ์Šค๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

๋จผ์ €, ์žฅ๋ฉด์€ ๋น›์˜ ๊ด€์ ์—์„œ ๋ Œ๋”๋ง๋ฉ๋‹ˆ๋‹ค. ๊ฐ fragment์˜ ๊นŠ์ด๋งŒ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์”ฌ(scene)์ด ํ‰์†Œ์™€ ๊ฐ™์ด ๋ Œ๋”๋ง๋˜์ง€๋งŒ ์ถ”๊ฐ€ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ตํ•ด ํ˜„์žฌ ์กฐ๊ฐ์ด ๊ทธ๋ฆผ์ž์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

 

"๊ทธ๋ฆผ์ž ์†์— ์žˆ๋Š” ๋ฌผ์ฒด" ํ…Œ์ŠคํŠธ๋Š” ์‚ฌ์‹ค ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ƒ˜ํ”Œ์ด ๋™์ผํ•œ ์ ์—์„œ ๊ทธ๋ฆผ์ž ๋งต๋ณด๋‹ค ๋น›์—์„œ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ์œผ๋ฉด ์”ฌ(scene)์— ๋น›์— ๋” ๊ฐ€๊นŒ์šด ๊ฐœ์ฒด๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ํ˜„์žฌ fragment๋Š” ๊ทธ๋ฆผ์ž์— ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋‹ค์Œ ์ด๋ฏธ์ง€๋Š” ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Shadowmap ๋ Œ๋”๋งํ•˜๊ธฐ

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” directional lights(๋ชจ๋“  ๊ด‘์„ ์ด ํ‰ํ–‰ํ•˜๋‹ค๊ณ  ๊ฐ„์ฃผ๋  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ๋Š” ์กฐ๋ช…)๋งŒ ๊ณ ๋ คํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Shadow Map ๋ Œ๋”๋ง์€ ์ง๊ต ํˆฌ์˜ ํ–‰๋ ฌ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. ์ง๊ต ํ–‰๋ ฌ์€ ์›๊ทผ๋ฒ•์ด ๊ณ ๋ ค๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ์ผ๋ฐ˜์ ์ธ ์›๊ทผ๋ฒ• ํˆฌ์˜ ํ–‰๋ ฌ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฌผ์ฒด๋Š” ์นด๋ฉ”๋ผ ๊ฐ€๊นŒ์ด์— ์žˆ๋Š” ๋ฉ€๋ฆฌ์žˆ๋“  ๋™์ผํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค.

 

๋ Œ๋” ๋Œ€์ƒ ๋ฐ MVP ๋งคํŠธ๋ฆญ์Šค ์„ค์ •

ํŠœํ† ๋ฆฌ์–ผ 14๋ถ€ํ„ฐ๋Š” ์‰์ด๋”์—์„œ ๋‚˜์ค‘์— ์•ก์„ธ์Šคํ•˜๊ธฐ ์œ„ํ•ด ์žฅ๋ฉด์„ ํ…์Šค์ฒ˜๋กœ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ๋Š” Shadow Map์„ ํฌํ•จํ•˜๊ธฐ ์œ„ํ•ด 1024x1024 16๋น„ํŠธ depth ํ…์Šค์ฒ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Shadow Map์—๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ 16๋น„ํŠธ๋กœ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’๋“ค์„ ์ž์œ ๋กญ๊ฒŒ ์‹œํ—˜ํ•ด๋ณด์„ธ์š”. ๋‚˜์ค‘์— ์ƒ˜ํ”Œ๋งํ•ด์•ผ ํ•˜๋ฏ€๋กœ depth ๋ Œ๋” ๋ฒ„ํผ๊ฐ€ ์•„๋‹Œ depth ํ…์Šค์ฒ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

// The framebuffer, which regroups 0, 1, or more textures, and 0 or 1 depth buffer.
 GLuint FramebufferName = 0;
 glGenFramebuffers(1, &FramebufferName);
 glBindFramebuffer(GL_FRAMEBUFFER, FramebufferName);

 // Depth texture. Slower than a depth buffer, but you can sample it later in your shader
 GLuint depthTexture;
 glGenTextures(1, &depthTexture);
 glBindTexture(GL_TEXTURE_2D, depthTexture);
 glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, 1024, 1024, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

 glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0);

 glDrawBuffer(GL_NONE); // No color buffer is drawn to.

 // Always check that our framebuffer is ok
 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
 return false;

๋น›์˜ ๊ด€์ ์—์„œ ์žฅ๋ฉด์„ ๋ Œ๋”๋งํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๋Š” MVP ๋งคํŠธ๋ฆญ์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค:

  • Projection ํ–‰๋ ฌ์€ X,Y ๋ฐ Z ์ถ•์—์„œ ๊ฐ๊ฐ ์ถ• ์ •๋ ฌ ์ƒ์ž(-10, 10), (-10,10), (-10, 20)์˜ ๋ชจ๋“  ๊ฒƒ์„ ํฌํ•จํ•˜๋Š” ์ง๊ต ํ–‰๋ ฌ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฐ’์€ ์ „์ฒด *๊ฐ€์‹œ์ ์ธ* ์žฅ๋ฉด์„ ํ•ญ์ƒ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์กŒ์œผ๋ฉฐ, ์ด์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ถ”๊ฐ€ ์ง„ํ–‰ ์„น์…˜์„ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.
  • View ํ–‰๋ ฌ์€ ์นด๋ฉ”๋ผ ๊ณต๊ฐ„์—์„œ ์กฐ๋ช… ๋ฐฉํ–ฅ์ด -Z๊ฐ€ ๋˜๋„๋ก ์›”๋“œ๋ฅผ ํšŒ์ „์‹œํ‚ต๋‹ˆ๋‹ค(ํŠœํ† ๋ฆฌ์–ผ 3 ์ฐธ์กฐ)
  • Model ํ–‰๋ ฌ์€ ์›ํ•˜๋Š” ๋Œ€๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
glm::vec3 lightInvDir = glm::vec3(0.5f,2,2);

 // Compute the MVP matrix from the light's point of view
 glm::mat4 depthProjectionMatrix = glm::ortho<float>(-10,10,-10,10,-10,20);
 glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, glm::vec3(0,0,0), glm::vec3(0,1,0));
 glm::mat4 depthModelMatrix = glm::mat4(1.0);
 glm::mat4 depthMVP = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;

 // Send our transformation to the currently bound shader,
 // in the "MVP" uniform
 glUniformMatrix4fv(depthMatrixID, 1, GL_FALSE, &depthMVP[0][0])

์‰์ด๋”

์ด ํŒจ์Šค ๋™์•ˆ ์‚ฌ์šฉ๋˜๋Š” ์‰์ด๋”๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. vertex ์‰์ด๋”๋Š” ๊ท ์งˆ ์ขŒํ‘œ์—์„œ ์ •์ ์˜ ์œ„์น˜๋ฅผ ๊ฐ„๋‹จํžˆ ๊ณ„์‚ฐํ•˜๋Š” ํ†ต๊ณผ ์‰์ด๋”์ž…๋‹ˆ๋‹ค:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;

// Values that stay constant for the whole mesh.
uniform mat4 depthMVP;

void main(){
 gl_Position =  depthMVP * vec4(vertexPosition_modelspace,1);
}

fragment ์‰์ด๋”๋Š” ๋‹จ์ˆœํ•˜๊ธฐ ๋•Œ๋ฌธ์— fragment์˜ ๊นŠ์ด๋ฅผ ์œ„์น˜ 0(์ฆ‰, ๊นŠ์ด ํ…์Šค์ฒ˜)์— ๊ธฐ๋กํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

#version 330 core

// Ouput data
layout(location = 0) out float fragmentdepth;

void main(){
    // Not really needed, OpenGL does it anyway
    fragmentdepth = gl_FragCoord.z;
}

Shadow Map์„ ๋ Œ๋”๋งํ•˜๋Š” ์†๋„๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ผ๋ฐ˜ ๋ Œ๋”๋ง๋ณด๋‹ค ๋‘ ๋ฐฐ ์ด์ƒ ๋น ๋ฆ…๋‹ˆ๋‹ค. ๊นŠ์ด์™€ ์ƒ‰์ƒ ๋Œ€์‹  ์ •๋ฐ€๋„๊ฐ€ ๋‚ฎ์€ ๊นŠ์ด๋งŒ ๊ธฐ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ชจ๋ฆฌ ๋Œ€์—ญํญ์€ GPU์—์„œ ๊ฐ€์žฅ ํฐ ์„ฑ๋Šฅ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ

๊ฒฐ๊ณผ ํ…์Šค์ฒ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์–ด๋‘์šด ์ƒ‰์ƒ์€ ์ž‘์€ z๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฒฝ์˜ ์˜ค๋ฅธ์ชฝ ์ƒ๋‹จ ๋ชจ์„œ๋ฆฌ๊ฐ€ ์นด๋ฉ”๋ผ ๊ทผ์ฒ˜์— ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜๋Œ€๋กœ ํฐ์ƒ‰์€ z=1(๋™์ผํ•œ ์ขŒํ‘œ)์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ ๋งค์šฐ ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

Shadowmap ์‚ฌ์šฉํ•˜๊ธฐ

๊ธฐ๋ณธ ์‰์ด๋”

์ด์ œ ํ‰์†Œ์˜ ์‰์ด๋”๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค. ๊ณ„์‚ฐํ•˜๋Š” ๊ฐ fragment์— ๋Œ€ํ•ด Shadow Map ๋’ค์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๋ฅผ ์œ„ํ•ด Shadow Map์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•œ ๊ณต๊ฐ„๊ณผ ๋™์ผํ•œ ๊ณต๊ฐ„์—์„œ ํ˜„์žฌ fragment์˜ ์œ„์น˜๋ฅผ ๊ณ„์‚ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ผ๋ฐ˜์ ์ธ MVP ํ–‰๋ ฌ๋กœ ํ•œ ๋ฒˆ ๋ณ€ํ™˜ํ•˜๊ณ  ๊นŠ์ด MVP ํ–‰๋ ฌ๋กœ ํ•œ ๋ฒˆ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ์•ฝ๊ฐ„์˜ ์†์ž„์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์  ์œ„์น˜์— ๊นŠ์ด๋ฅผ ๊ณฑํ•˜๋ฉด MVP๋Š” [-1,1]์— ์žˆ๋Š” ๊ท ์ผํ•œ ์ขŒํ‘œ๋ฅผ ์ œ๊ณตํ•˜์ง€๋งŒ ํ…์Šค์ฒ˜ ์ƒ˜ํ”Œ๋ง์€ [0,1]์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, ํ™”๋ฉด ์ค‘์•™์— ์žˆ๋Š” fragment๋Š” ๊ท ์ผํ•œ ์ขŒํ‘œ๋กœ (0,0)์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์งˆ๊ฐ ์ค‘๊ฐ„์€ ์ƒ˜ํ”Œ๋งํ•ด์•ผ ํ•˜๋ฏ€๋กœ UV๋Š” (0.5,05)์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด๊ฒƒ์€ fragment shader์—์„œ ์ง์ ‘ fetch ์ขŒํ‘œ๋ฅผ ์กฐ์ •ํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋‹จ์ˆœํžˆ ์ขŒํ‘œ๋ฅผ 2(๋Œ€๊ฐ์„  : [-1.1] -> [-0.5,0.5])๋กœ ๋‚˜๋ˆ„๊ณ  ๋ณ€ํ™˜ํ•˜๋Š” ํ–‰๋ ฌ(์•„๋ž˜ ํ–‰ : [-0.5,0.5]->[0,1])์„ ๊ณฑํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

glm::mat4 biasMatrix(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
glm::mat4 depthBiasMVP = biasMatrix*depthMVP;

์ด์ œ vertex ์‰์ด๋”๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „๊ณผ ๋™์ผํ•˜์ง€๋งŒ 1:1์ด ์•„๋‹Œ 2๊ฐœ์˜ ์œ„์น˜๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค:

  • gl_Position ์€ ํ˜„์žฌ ์นด๋ฉ”๋ผ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ •์ ์˜ ์œ„์น˜์ž…๋‹ˆ๋‹ค.
  • ShadowCoord๋Š” ๋งˆ์ง€๋ง‰ ์นด๋ฉ”๋ผ(๋น›)์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ •์ ์˜ ์œ„์น˜์ž…๋‹ˆ๋‹ค.
// Output position of the vertex, in clip space : MVP * position
gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

// Same, but with the light's view matrix
ShadowCoord = DepthBiasMVP * vec4(vertexPosition_modelspace,1);

๊ทธ๋Ÿฐ ๋‹ค์Œ fragment ์‰์ด๋”๋Š” ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค:

  • texture(shadowMap, ShadowCoord.xy).z ๋Š” ๋น›๊ณผ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋น›์„ ์ฐจ๋‹จํ•˜๋Š” ํ์ƒ‰์ž ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  • ShadowCoord.z๋Š” ๋น›๊ณผ ํ˜„์žฌ fragment ์‚ฌ์ด์˜ ๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค.

...๋”ฐ๋ผ์„œ ํ˜„์žฌ fragment๊ฐ€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํ์ƒ‰์ž๋ณด๋‹ค ๋ฉ€๋ฆฌ ์žˆ์œผ๋ฉด, ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ (ํ•ด๋‹น ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ํ์ƒ‰์ž์˜) ๊ทธ๋ฆผ์ž์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

float visibility = 1.0;
if ( texture( shadowMap, ShadowCoord.xy ).z  <  ShadowCoord.z){
    visibility = 0.5;
}

์šฐ๋ฆฌ๋Š” ์ด ์ง€์‹์„ ์ด์šฉํ•˜์—ฌ ์Œ์˜์„ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ฃผ๋ณ€ ์ƒ‰์ƒ์€ ์ˆ˜์ •๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒํ™œ ์†์˜ ๋ชฉ์ ์€ ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋ฆผ์ž ์†์— ์žˆ์„ ๋•Œ๋„ ๋“ค์–ด์˜ค๋Š” ๋น›์„ ๊ฐ€์งœ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค(๋˜๋Š” ๋ชจ๋“  ๊ฒƒ์ด ์ˆœ์ˆ˜ํ•œ ๊ฒ€์€์ƒ‰์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค)

color =
 // Ambient : simulates indirect lighting
 MaterialAmbientColor +
 // Diffuse : "color" of the object
 visibility * MaterialDiffuseColor * LightColor * LightPower * cosTheta+
 // Specular : reflective highlight, like a mirror
 visibility * MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5);

๊ฒฐ๊ณผ - ์‰๋„์šฐ ์•„ํฌ๋„ค

๋‹ค์Œ์€ ํ˜„์žฌ ์ฝ”๋“œ์˜ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค. ๋ถ„๋ช…ํžˆ, ์•„์ด๋””์–ด๋Š” ๋›ฐ์–ด๋‚˜์ง€๋งŒ , ํ’ˆ์งˆ์€ ๋ฐ›์•„๋“ค์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด ์ด๋ฏธ์ง€์˜ ๊ฐ ๋ฌธ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ฝ”๋“œ์—๋Š” ShadowMap๊ณผ ShadowMap_simple์˜ ๋‘ ๊ฐ€์ง€ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ์œผ๋ฉฐ, ๋‘˜ ์ค‘ ๋” ๋งˆ์Œ์— ๋“œ๋Š” ๊ฒƒ์œผ๋กœ ์‹œ์ž‘ํ•˜์„ธ์š”.

๊ฐ„๋‹จํ•œ ๋ฒ„์ „์€ ์œ„์˜ ์ด๋ฏธ์ง€๋งŒํผ ํ’ˆ์งˆ์ด ์ข‹์ง€ ์•Š์ง€๋งŒ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ๋” ์‰ฝ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ์ ๋“ค

Shadow acne

๊ฐ€์žฅ ๋ช…๋ฐฑํ•œ ๋ฌธ์ œ์ ์€ shadow acne์ด๋‹ค:

์ด ํ˜„์ƒ์€ ๊ฐ„๋‹จํ•œ ์ด๋ฏธ์ง€๋กœ ์‰ฝ๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

์ด์— ๋Œ€ํ•œ ์ผ๋ฐ˜์ ์ธ "์ˆ˜์ •"์€ error margin์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ fragment์˜ depth(๋‹ค์‹œ๋งํ•ด, ๋น› ๊ณต๊ฐ„)๊ฐ€ ๋ผ์ดํŠธ๋งต ๊ฐ’์—์„œ ์ •๋ง ๋ฉ€๋ฆฌ ๋–จ์–ด์ ธ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์Œ์˜ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ํŽธํ–ฅ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:

float bias = 0.005;
float visibility = 1.0;
if ( texture( shadowMap, ShadowCoord.xy ).z  <  ShadowCoord.z-bias){
    visibility = 0.5;
}

๊ฒฐ๊ณผ๋ฌผ์€ ํ›จ์”ฌ ๋‚˜์•„์ง‘๋‹ˆ๋‹ค:

ํ•˜์ง€๋งŒ, ์—ฌ๋Ÿฌ๋ถ„์€ ์šฐ๋ฆฌ์˜ ํŽธ๊ฒฌ ๋•Œ๋ฌธ์— ๋•…๊ณผ ๋ฒฝ ์‚ฌ์ด์˜ ์ธ๊ณต๋ฌผ์ด ๋” ๋‚˜๋น ์กŒ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฐจ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒŒ๋‹ค๊ฐ€, 0.005์˜ ํŽธํ–ฅ์€ ๋•…์—์„œ๋Š” ๋„ˆ๋ฌด ๋งŽ์ด ๋ณด์ด์ง€๋งŒ, ๊ณก๋ฉด์—์„œ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: ๋ช‡๋ช‡ ์ธ๊ณต๋ฌผ๋“ค์€ ์‹ค๋ฆฐ๋”์™€ ๊ตฌ์— ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ธฐ์šธ๊ธฐ์— ๋”ฐ๋ผ ์น˜์šฐ์นจ์„ ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

float bias = 0.005*tan(acos(cosTheta)); // cosTheta is dot( n,l ), clamped between 0 and 1
bias = clamp(bias, 0,0.01);

Shadow acne๋Š” ์ด์ œ, ๊ตฌ๋ถ€๋Ÿฌ์ง„ ํ‘œ๋ฉด์—์„œ๋„ ์‚ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค.

์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ์— ๋”ฐ๋ผ ์ž‘๋™ํ•˜๊ฑฐ๋‚˜ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ ShadowMap์—์„œ ๋’ท๋ฉด๋งŒ ๋ Œ๋”๋งํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ๋‘๊บผ์šด ๋ฒฝ์„ ๊ฐ€์ง„ ํŠน๋ณ„ํ•œ ๊ธฐํ•˜ํ•™์  ๊ตฌ์กฐ(๋‹ค์Œ ์„น์…˜ - Peter Panning ์ฐธ์กฐ)๋ฅผ ๊ฐ–๋„๋ก ๊ฐ•์š”ํ•˜์ง€๋งŒ, ์ ์–ด๋„ acne๋Š” ๊ทธ๋ฆผ์ž์— ์žˆ๋Š” ํ‘œ๋ฉด์— ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ShadowMap์„ ๋ Œ๋”๋งํ•  ๋•Œ ์ „๋ฉด ์‚ผ๊ฐํ˜•์„ ์ž˜๋ผ๋ƒ…๋‹ˆ๋‹ค.

        // We don't use bias in the shader, but instead we draw back faces,
        // which are already separated from the front faces by a small distance
        // (if your geometry is made this way)
        glCullFace(GL_FRONT); // Cull front-facing triangles -> draw only back-facing triangles

๊ทธ๋ฆฌ๊ณ  ์”ฌ(scene)์„ ๋ Œ๋”๋งํ•  ๋•Œ๋Š” ์ •์ƒ์ ์œผ๋กœ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค(๋’ท๋ฉด ์ ˆ๋‹จ)

         glCullFace(GL_BACK); // Cull back-facing triangles -> draw only front-facing triangles

์ด ๋ฐฉ๋ฒ•์€ ํŽธํ–ฅ ์™ธ์—๋„ ์ฝ”๋“œ์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Peter Panning

์šฐ๋ฆฌ๋Š” ๋” ์ด์ƒ Shadow acne๊ฐ€ ์—†์ง€๋งŒ, ์—ฌ์ „ํžˆ ์ž˜๋ชป๋œ ์Œ์˜์˜ ๋•…์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๋ฒฝ์„ ๋‚ ์•„๋‹ค๋‹ˆ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค(์ดํ›„ "ํ”ผํ„ฐ ํŒจ๋‹"์ด๋ผ๋Š” ์šฉ์–ด). ์‚ฌ์‹ค, ํŽธํ–ฅ(bias)์„ ๋”ํ•˜๋Š” ๊ฒƒ์€ ์ƒํ™ฉ์„ ๋” ์•…ํ™”์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋งค์šฐ ์‰ฝ๊ฒŒ ๊ณ ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–‡์€ ๊ธฐํ•˜ํ•™์  ๊ตฌ์กฐ๋ฅผ ํ”ผํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‘ ๊ฐ€์ง€ ์ด์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋จผ์ €, ํ”ผํ„ฐ ํŒจ๋‹์„ ํ•ด๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ๊ธฐํ•˜ํ•™์ด ์—ฌ๋Ÿฌ๋ถ„์˜ ํŽธ๊ฒฌ๋ณด๋‹ค ๋” ๊นŠ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์ค€๋น„๊ฐ€ ๋‹ค ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • ๋‘ ๋ฒˆ์งธ๋กœ, ๋ผ์ดํŠธ๋งต์„ ๋ Œ๋”๋งํ•  ๋•Œ ํ›„๋ฉด ์ ˆ๋‹จ ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์ด์ œ ๋ฒฝ์˜ ๋‹ค๊ฐํ˜•์ด ๋น›์„ ํ–ฅํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ๋‹ค๊ฐํ˜•์€ ๋’ท๋ฉด ์ ˆ๋‹จ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”๋ง๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹จ์ ์€ ๋ Œ๋”๋งํ•  ์‚ผ๊ฐํ˜•์ด ๋” ๋งŽ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(ํ”„๋ ˆ์ž„๋‹น ๋‘ ๋ฒˆ!)

Aliasing

์ด ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์—ฌ๋Ÿฌ๋ถ„์€ ๊ทธ๋ฆผ์ž์˜ ๊ฒฝ๊ณ„์— ์—ฌ์ „ํžˆ ์•จ๋ฆฌ์–ด์‹ฑ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์ฐจ๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ํ•œ ํ”ฝ์…€์€ ํฐ์ƒ‰์ด๊ณ  ๋‹ค์Œ ํ”ฝ์…€์€ ๊ฒ€์€์ƒ‰์ž…๋‹ˆ๋‹ค. ๊ทธ ์‚ฌ์ด์— ๋งค๋„๋Ÿฌ์šด ์ „ํ™˜์ด ์—†์Šต๋‹ˆ๋‹ค.

PCF

์ด๋ฅผ ๊ฐœ์„ ํ•˜๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ShadowMap์˜ ์ƒ˜ํ”Œ๋Ÿฌ ์œ ํ˜•์„ Sampler2D ์‰์ด๋”๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฒฐ๊ณผ์ ์œผ๋กœ ShadowMap์„ ํ•œ ๋ฒˆ ์ƒ˜ํ”Œ๋งํ•˜๋ฉด ํ•˜๋“œ์›จ์–ด๊ฐ€ ์‹ค์ œ๋กœ ์ธ์ ‘ํ•œ ํ…์…€๋„ ์ƒ˜ํ”Œ๋งํ•˜๊ณ  ๋ชจ๋“  ํ…์…€์— ๋Œ€ํ•ด ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉฐ ๋น„๊ต ๊ฒฐ๊ณผ์˜ ์ด์ค‘ ์„ ํ˜• ํ•„ํ„ฐ๋ง๊ณผ ํ•จ๊ป˜ [0,1]์˜ ๋ถ€๋™ ์†Œ์ˆ˜์ ์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

 

์˜ˆ๋ฅผ ๋“ค์–ด, 0.5๋Š” ๋‘ ๊ฐœ์˜ ํ‘œ๋ณธ์ด ๊ทธ๋ฆผ์ž์— ์žˆ๊ณ  ๋‘ ๊ฐœ์˜ ํ‘œ๋ณธ์ด ๋น›์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

ํ•„ํ„ฐ๋ง๋œ ๊นŠ์ด ๋งต์˜ ๋‹จ์ผ ์ƒ˜ํ”Œ๋ง๊ณผ ๋™์ผํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค! ๋น„๊ต๋Š” ํ•ญ์ƒ true ๋˜๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. PCF๋Š” 4 "true ๋˜๋Š” false"์˜ ๋ณด๊ฐ„๊ฐ’์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๋ณด์‹œ๋‹ค์‹œํ”ผ ๊ทธ๋ฆผ์ž ํ…Œ๋‘๋ฆฌ๋Š” ๋งค๋„๋Ÿฝ์ง€๋งŒ ๊ทธ๋ฆผ์ž ๋งต์˜ ํ…์Šค์ฒ˜๋Š” ์—ฌ์ „ํžˆ ๋ณด์ž…๋‹ˆ๋‹ค.

Poisson Sampling

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ ์‰๋„์šฐ ๋งต์„ ํ•œ ๋ฒˆ์ด ์•„๋‹ˆ๋ผ N๋ฒˆ ์ƒ˜ํ”Œ๋งํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. PCF์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด N์ด ์ž‘๋”๋ผ๋„ ๋งค์šฐ ์ข‹์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ƒ˜ํ”Œ 4๊ฐœ์— ๋Œ€ํ•œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

for (int i=0;i<4;i++){
  if ( texture( shadowMap, ShadowCoord.xy + poissonDisk[i]/700.0 ).z  <  ShadowCoord.z-bias ){
    visibility-=0.2;
  }
}

poissonDisk๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ •์˜๋œ ์ƒ์ˆ˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค:

vec2 poissonDisk[4] = vec2[](
  vec2( -0.94201624, -0.39906216 ),
  vec2( 0.94558609, -0.76890725 ),
  vec2( -0.094184101, -0.92938870 ),
  vec2( 0.34495938, 0.29387760 )
);

์ด ๋ฐฉ๋ฒ•์€ ํ†ต๊ณผํ•  ์‰๋„์šฐ ๋งต ์ƒ˜ํ”Œ ์ˆ˜์— ๋”ฐ๋ผ ์ƒ์„ฑ๋œ fragment๊ฐ€ ๋‹ค์†Œ ์–ด๋‘์›Œ์ง‘๋‹ˆ๋‹ค.

700.0 ์ƒ์ˆ˜๋Š” ํ‘œ๋ณธ์ด "ํ™•์‚ฐ"๋˜๋Š” ์ •๋„๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ์ ๊ฒŒ ํผ๋œจ๋ฆฌ๋ฉด ๋‹ค์‹œ ์•จ๋ฆฌ์–ด์‹ฑ์ด ๋ฐœ์ƒํ•˜๊ณ , ๋„ˆ๋ฌด ๋งŽ์ด ํผ๋œจ๋ฆฌ๋ฉด ๋ฐด๋”ฉ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.*(์ด ์Šคํฌ๋ฆฐ์ƒท์€ ๋” ๊ทน์ ์ธ ํšจ๊ณผ๋ฅผ ์œ„ํ•ด PCF๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋Œ€์‹  16๊ฐœ์˜ ์ƒ˜ํ”Œ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.*

Stratified Poisson Sampling

ํ”ฝ์…€๋งˆ๋‹ค ๋‹ค๋ฅธ ์ƒ˜ํ”Œ์„ ์„ ํƒํ•˜์—ฌ ์ด ๋ฐด๋”ฉ์„ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค : Stratified Poisson ๋˜๋Š” Rotated Poisson

Stratified๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ํ‘œ๋ณธ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. Rotated๋Š” ํ•ญ์ƒ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋žœ๋ค ํšŒ์ „์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋กœ ๋‹ค๋ฅด๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Stratified ๋ฒ„์ „๋งŒ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

์ด์ „ ๋ฒ„์ „๊ณผ์˜ ์œ ์ผํ•œ ์ฐจ์ด์ ์€ ๋žœ๋ค ์ธ๋ฑ์Šค๋กœ poissonDisk๋ฅผ ์ธ๋ฑ์‹ฑํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค:

    for (int i=0;i<4;i++){
        int index = // A random number between 0 and 15, different for each pixel (and each i !)
        visibility -= 0.2*(1.0-texture( shadowMap, vec3(ShadowCoord.xy + poissonDisk[index]/700.0,  (ShadowCoord.z-bias)/ShadowCoord.w) ));
    }

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋กœ ๋‚œ์ˆ˜๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ,[0,1]์—์„œ ๋‚œ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

    float dot_product = dot(seed4, vec4(12.9898,78.233,45.164,94.673));
    return fract(sin(dot_product) * 43758.5453);

์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ seed4๋Š” i(4๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ์œ„์น˜์—์„œ ์ƒ˜ํ”Œ์„ ์ฑ„์ทจํ•  ์ˆ˜ ์žˆ๋„๋ก)์™€ ...์˜ ์กฐํ•ฉ์ด ๋ฉ๋‹ˆ๋‹ค.

gl_FragCord(ํ™”๋ฉด์˜ ํ”ฝ์…€ ์œ„์น˜)๋˜๋Š” Position_worldspace๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

        //  - A random sample, based on the pixel's screen location.
        //    No banding, but the shadow moves with the camera, which looks weird.
        int index = int(16.0*random(gl_FragCoord.xyy, i))%16;
        //  - A random sample, based on the pixel's position in world space.
        //    The position is rounded to the millimeter to avoid too much aliasing
        //int index = int(16.0*random(floor(Position_worldspace.xyz*1000.0), i))%16;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์€ ํŒจํ„ด์ด ์‚ฌ๋ผ์ง€๊ณ  ์‹œ๊ฐ์  ๋…ธ์ด์ฆˆ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ž˜ ์ˆ˜ํ–‰๋œ ๋…ธ์ด์ฆˆ๋Š” ์ข…์ข… ์ด๋Ÿฌํ•œ ํŒจํ„ด๋ณด๋‹ค ๋œ ๋ถˆ์พŒํ•ฉ๋‹ˆ๋‹ค.

์„ธ ๊ฐ€์ง€ ๊ตฌํ˜„์— ๋Œ€ํ•œ ์˜ˆ๋Š” tutorial16/ShadowMapping.fragmentshader ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๋” ๋‚˜์•„๊ฐ€๊ธฐ

์ด ๋ชจ๋“  ๋ฐฉ๋ฒ•์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ , ์šฐ๋ฆฌ์˜ ๊ทธ๋ฆผ์ž๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Early bailing

๊ฐ fragment์— ๋Œ€ํ•ด 16๊ฐœ์˜ ํ‘œ๋ณธ์„ ์ถ”์ถœํ•˜๋Š” ๋Œ€์‹ (๋‹ค์‹œ ๋งํ•˜๋ฉด ๋งŽ์€ ์–‘) 4๊ฐœ์˜ ๋ฉ€๋ฆฌ ์žˆ๋Š” ํ‘œ๋ณธ์„ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๊ทธ๋“ค ๋ชจ๋‘๊ฐ€ ๋น›์ด๋‚˜ ๊ทธ๋ฆผ์ž ์†์— ์žˆ๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ 16๊ฐœ์˜ ์ƒ˜ํ”Œ ๋ชจ๋‘๊ฐ€ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋ƒˆ์„ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: Early bailing. ๋งŒ์•ฝ ์–ด๋–ค ๊ฒƒ๋“ค์ด ๋‹ค๋ฅด๋‹ค๋ฉด, ์—ฌ๋Ÿฌ๋ถ„์€ ์•„๋งˆ๋„ ๊ทธ๋ฆผ์ž ๊ฒฝ๊ณ„์— ์žˆ์„ ๊ฒƒ์ด๊ธฐ ๋Œ€๋ฌธ์— 16๊ฐœ์˜ ์ƒ˜ํ”Œ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Spot lights

์ŠคํฌํŠธ๋ผ์ดํŠธ๋ฅผ ๋‹ค๋ฃจ๋Š” ๋ฐ๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๊ฑฐ์˜ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ํ™•์‹คํ•œ ๊ฒƒ์€ ์ง๊ต ํˆฌ์šฉ ํ–‰๋ ฌ์„ ์›๊ทผ ํˆฌ์˜ ํ–‰๋ ฌ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

glm::vec3 lightPos(5, 20, 20);
glm::mat4 depthProjectionMatrix = glm::perspective<float>(glm::radians(45.0f), 1.0f, 2.0f, 50.0f);
glm::mat4 depthViewMatrix = glm::lookAt(lightPos, lightPos-lightInvDir, glm::vec3(0,1,0));

๊ฐ™์€ ๊ฒƒ์ด์ง€๋งŒ, orthographic frustum ๋Œ€์‹ ์— perspective frustum์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

texture2Dproj ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›๊ทผ ๋ถ„ํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.(์ž์Šต์„œ4- ํ–‰๋ ฌ์˜ ๊ฐ์ฃผ ์ฐธ์กฐ)

 

๋‘๋ฒˆ์งธ ๋‹จ๊ณ„๋Š” ์‰์ด๋”์˜ ๊ด€์ ์—์„œ ๊ณ ๋ คํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.(์ž์Šต์„œ 4- ํ–‰๋ ฌ์˜ ๊ฐ์ฃผ ์ฐธ์กฐ). ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ํˆฌ์‹œ ํˆฌ์˜ ํ–‰๋ ฌ์€ ์‹ค์ œ๋กœ ์–ด๋–ค ํˆฌ์‹œ๋„ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ํ•˜๋“œ์›จ์–ด์—์„œ ์˜ˆ์ƒ ์ขŒํ‘œ๋ฅผ w๋กœ ๋‚˜๋ˆ„์–ด ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์„œ, ์šฐ๋ฆฌ๋Š” ์‰์ด๋”์˜ ๋ณ€ํ˜•์„ ๋ชจ๋ฐฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ ์ž์‹ ์„ ๋ถ„ํ• ํ•˜๋Š” ๊ด€์ ์„ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ, orthographic ํ–‰๋ ฌ์€ ํ•ญ์ƒ w=1์˜ ๊ท ์งˆ ๋ฒกํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๋ฏ€๋กœ ์›๊ทผ๋ฒ•์„ ์ƒ์„ฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค).

 

GLSL์—์„œ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ์ค„์€ ๋‚ด์žฅ textureProj ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ ์ •ํ™•ํ•˜๊ฒŒ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

if ( texture( shadowMap, (ShadowCoord.xy/ShadowCoord.w) ).z  <  (ShadowCoord.z-bias)/ShadowCoord.w )
if ( textureProj( shadowMap, ShadowCoord.xyw ).z  <  (ShadowCoord.z-bias)/ShadowCoord.w )

Point lights

๋™์ผํ•˜์ง€๋งŒ depth ๊ทœ๋ธŒ ๋งต์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ๋ธŒ ๋งต์€ ํ๋ธŒ์˜ ๊ฐ ๋ฉด์— ํ•˜๋‚˜์”ฉ ์žˆ๋Š” 6๊ฐœ์˜ ํ…์Šค์ฒ˜ ์„ธํŠธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ํ‘œ์ค€ UV ์ขŒํ‘œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐฉํ–ฅ์„ ๋‚˜ํƒ€๋‚ด๋Š” 3D ๋ฒกํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊นŠ์ด๋Š” ๊ณต๊ฐ„์˜ ๋ชจ๋“  ๋ฐฉํ–ฅ์— ๋Œ€ํ•ด ์ €์žฅ๋˜๋ฏ€๋กœ ์ ๊ด‘ ์ฃผ์œ„์— ๊ทธ๋ฆผ์ž๊ฐ€ ๋“œ๋ฆฌ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๊ฐœ์˜ ๋น› ํ˜ผํ•ฉ

์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์กฐ๋ช…์„ ์ฒ˜๋ฆฌํ•˜์ง€๋งŒ ๊ฐ ์กฐ๋ช…์€ ๊ทธ๋ฆผ์ž ๋งต์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์žฅ๋ฉด์„ ์ถ”๊ฐ€๋กœ ๋ Œ๋”๋งํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Shadow๋ฅผ ์ ์šฉํ•  ๋•Œ ์—„์ฒญ๋‚œ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ๋Œ€์—ญํญ์ด ๋งค์šฐ ๋น ๋ฅด๊ฒŒ ์ œํ•œ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋™ ๋น› frustum

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ์ „์ฒด ์žฅ๋ฉด์„ ํฌํ•จํ•˜๋„๋ก ์†์œผ๋กœ ๋งŒ๋“  ๋น› frustum์ž…๋‹ˆ๋‹ค. ์ด ์ œํ•œ๋œ ์˜ˆ์ œ์—์„œ๋Š” ์ด ์ž‘์—…์ด ์ž‘๋™ํ•˜์ง€๋งŒ ์ด ์ž‘์—…์€ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋‹น์‹ ์˜ ์ง€๋„๊ฐ€ 1Km x 1Km์ด๋ผ๋ฉด, ๋‹น์‹ ์˜ 1024x1024 ๊ทธ๋ฆผ์ž ์ง€๋„์˜ ๊ฐ ํ…์ŠคํŠธ๋Š” 1ํ‰๋ฐฉ๋ฏธํ„ฐ๋ฅผ ์ฐจ์ง€ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ํ˜•ํŽธ ์—†์Šต๋‹ˆ๋‹ค. ์กฐ๋ช…์˜ ํˆฌ์˜ ํ–‰๋ ฌ์€ ๊ฐ€๋Šฅํ•œํ•œ ํƒ€์ดํŠธํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

 

์ŠคํฌํŠธ๋ผ์ดํŠธ์˜ ๊ฒฝ์šฐ ๋ฒ”์œ„๋ฅผ ์กฐ์ •ํ•˜์—ฌ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํƒœ์–‘๊ณผ ๊ฐ™์€ ๋ฐฉํ–ฅ ์กฐ๋ช…์€ ๋” ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ๋“ค์€ ์ •๋ง๋กœ ์ „์ฒด ์žฅ๋ฉด์„ ๋น„์ถ”์ฃ . ๊ด‘๊ฒฉ์ž๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค:

  1. ์ž ์žฌ์  ๊ทธ๋ฆผ์ž ์ˆ˜์‹ ๊ธฐ ๋˜๋Š” ์ค„์—ฌ์„œ PSR์€ ๋น›์˜ frustum, view frustum ๋ฐ ์žฅ๋ฉด ๊ฒฝ๊ณ„ ์ƒ์ž์— ๋™์‹œ์— ์†ํ•˜๋Š” ๊ฐ์ฒด ์ž…๋‹ˆ๋‹ค. ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด, ์ด ๋ฌผ์ฒด๋“ค์€ ์Œ์˜์„ ๋ฐ›๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ์นด๋ฉ”๋ผ์™€ ๋น›์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ์ž ์žฌ์  ๊ทธ๋ฆผ์ž ์บ์Šคํ„ฐ(PCF)๋Š” ๋ชจ๋‘ ์ž ์žฌ์  ๊ทธ๋ฆผ์ž ์ˆ˜์‹ ๊ธฐ์ด๋ฉฐ, ๊ทธ ์‚ฌ์ด์— ์žˆ๋Š” ๋ชจ๋“  ๋ฌผ์ฒด(๋ฌผ์ฒด๋Š” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ณด์ด๋Š” ๊ทธ๋ฆผ์ž๋ฅผ ๋“œ๋ฆฌ์šธ ์ˆ˜ ์žˆ์Œ)์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๋น› ํˆฌ์˜ ํ–‰๋ ฌ์„ ๊ณ„์‚ฐํ•˜๋ ค๋ฉด ๋ณด์ด๋Š” ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋„ˆ๋ฌด ๋ฉ€๋ฆฌ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๊ฒฝ๊ณ„ ์ƒ์ž๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ๊ณ„ ์ƒ์ž์™€ ์กฐ๋ช… ์‚ฌ์ด์— ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ƒˆ ๊ฒฝ๊ณ„ ์ƒ์ž๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค(๊ทธ๋Ÿฌ๋‚˜ ์ด๋ฒˆ์—๋Š” ์กฐ๋ช… ๋ฐฉํ–ฅ์„ ๋”ฐ๋ผ ์ •๋ ฌ๋จ).

 

์ด๋Ÿฌํ•œ ์ง‘ํ•ฉ์˜ ์ •ํ™•ํ•œ ๊ณ„์‚ฐ์—๋Š” ๋ณผ๋ก ๊ป์งˆ ๊ต์ฐจ์  ๊ณ„์‚ฐ์ด ํฌํ•จ๋˜์ง€๋งŒ, ์ด ๋ฐฉ๋ฒ•์€ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค.

 

์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ทธ๋ฆผ์ž ๋งต ํ•ด์ƒ๋„๊ฐ€ ๊ฐ‘์ž๊ธฐ ์ฆ๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌผ์น˜๊ฐ€ frustum์—์„œ ์‚ฌ๋ผ์ง€๋ฉด ํŒํ•‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๊ณ„๋‹จ์‹ Shadow Map์—๋Š” ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ค์šฐ๋ฉฐ ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๊ฐ’์„ ๋งค๋„๋Ÿฝ๊ฒŒ ํ•˜์—ฌ ๋ณด์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ง€์ˆ˜ shadow maps

์ง€์ˆ˜ ๊ทธ๋ฆผ์ž ๋งต์€ ๊ทธ๋ฆผ์ž์— ์žˆ์ง€๋งŒ ๋น› ํ‘œ๋ฉด ๊ทผ์ฒ˜์— ์žˆ๋Š” fragment๊ฐ€ ์‹ค์ œ๋กœ "๊ฐ€์šด๋ฐ ์–ด๋”˜๊ฐ€"๋ผ๊ณ  ๊ฐ€์ •ํ•˜์—ฌ ์•จ๋ฆฌ์–ด์‹ฑ์„ ์ œํ•œํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ๊ฐ€ ๋”์ด์ƒ ์ด์ง„๋ฒ•์ด ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ์ œ์™ธํ•˜๋ฉด ์ด๋Š” ํŽธํ–ฅ๊ณผ ๊ด€๋ จ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น›์ด ์žˆ๋Š” ํ‘œ๋ฉด๊นŒ์ง€์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์ฆ๊ฐ€ํ•˜๋ฉด fragment๊ฐ€ ์ ์  ์–ด๋‘์›Œ์ง‘๋‹ˆ๋‹ค.

 

์ด๊ฒƒ์€ ๋ช…๋ฐฑํžˆ ๋ถ€์ •ํ–‰์œ„์ด๋ฉฐ, ๋‘ ๋ฌผ์ฒด๊ฐ€ ๊ฒน์น  ๋•Œ ์ธ๊ณต๋ฌผ์ด ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋น›-๊ณต๊ฐ„ ์›๊ทผ๋ฒ• shadow maps

LiSPSM์€ ์นด๋ฉ”๋ผ ๊ทผ์ฒ˜์—์„œ ๋” ์ •ํ™•ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๋น› ํˆฌ์˜ ํ–‰๋ ฌ์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ "๋ถˆ์•ˆ์ •ํ•œ frustra"์˜ ๊ฒฝ์šฐ์—๋Š” ํŠนํžˆ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๋ถ„์€ ๋ฐฉํ–ฅ์„ ๋ฐ”๋ผ์ง€๋งŒ, ์Šคํฟ๋ผ์ดํŠธ๋Š” ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์„ ๋ฐ”๋ผ๋ด…๋‹ˆ๋‹ค. ๋‹น์‹ ์€ ๋น› ๊ทผ์ฒ˜, ์ฆ‰ ๋‹น์‹ ์œผ๋กœ๋ถ€ํ„ฐ ๋ฉ€๋ฆฌ ๋–จ์–ด์ง„ ๊ณณ์— ๋งŽ์€ ๊ทธ๋ฆผ์ž ์ง€๋„ ์ •๋ฐ€๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ๋‹น์‹ ์ด ๊ฐ€์žฅ ํ•„์š”๋กœ ํ•˜๋Š” ์นด๋ฉ”๋ผ ๊ทผ์ฒ˜์— ๋‚ฎ์€ ํ•ด์ƒ๋„๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฌ๋‚˜ LiSPSM์€ ๊ตฌํ˜„ํ•˜๊ธฐ๊ฐ€ ๊นŒ๋‹ค๋กญ์Šต๋‹ˆ๋‹ค. ๊ตฌํ˜„์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

๊ณ„๋‹จ์‹ shadow maps

CSM์€ LiSPSM๊ณผ ์™„์ „ํžˆ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฃจ์ง€๋งŒ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ view frustum์˜ ์—ฌ๋Ÿฌ ๋ถ€๋ถ„์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ ๊ฐœ์˜(2-4) ํ‘œ์ค€ ๊ทธ๋ฆผ์ž ๋งต์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ๊ฒƒ์€ ์ฒซ ๋ฒˆ์งธ ๋ฏธํ„ฐ๋ฅผ ๋‹ค๋ฃจ๊ธฐ ๋•Œ๋ฌธ์— ๊ฝค ์ž‘์€ ๊ตฌ์—ญ์— ๋Œ€ํ•ด์„œ๋Š” ํ›Œ๋ฅญํ•œ ํ•ด์ƒ๋„๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ทธ๋ฆผ์ž ์ง€๋„๋Š” ๋” ๋จผ ๋ฌผ์ฒด๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ shadow map์€ ์žฅ๋ฉด์˜ ํฐ ๋ถ€๋ถ„์„ ๋‹ค๋ฃจ์ง€๋งŒ, ๊ด€์  ๋•Œ๋ฌธ์— ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๊ตฌ์—ญ๋ณด๋‹ค ์‹œ๊ฐ์ ์œผ๋กœ ๋” ์ค‘์š”ํ•˜์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

๊ณ„๋‹จ์‹ ์‰๋„์šฐ ๋งต์€ ์ž‘์„ฑ ๋‹น์‹œ(2012๋…„) ์ตœ๊ณ ์˜ ๋ณต์žก์„ฑ/ํ’ˆ์งˆ ๋น„์œจ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋งŽ์€ ๊ฒฝ์šฐ์— ์„ ํƒ์˜ ํ•ด๊ฒฐ์ฑ…์ž…๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

๋ณด์‹œ๋‹ค์‹œํ”ผ, ๊ทธ๋ฆผ์ž ์ง€๋„๋Š” ๋ณต์žกํ•œ ์ฃผ์ œ์ž…๋‹ˆ๋‹ค. ๋งค๋…„ ์ƒˆ๋กœ์šด ๋ณ€ํ˜•๊ณผ ๊ฐœ์„ ์‚ฌํ•ญ์ด ๋ฐœํ‘œ๋˜๊ณ  ์žˆ์œผ๋ฉฐ, ํ˜„์žฌ๋กœ์„œ๋Š” ์–ด๋–ค ์†”๋ฃจ์…˜๋„ ์™„๋ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๋‹คํ–‰ํžˆ, ์ œ์‹œ๋œ ๋Œ€๋ถ€๋ถ„์˜ ๋ฐฉ๋ฒ•์€ ํ•จ๊ป˜ ํ˜ผํ•ฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋น› ๊ณต๊ฐ„ ๊ด€์ ์—์„œ ๊ณ„์‚ฐ์‹ shadow map์„ PCF๋กœ ๋งค๋„๋Ÿฝ๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์™„๋ฒฝํ•˜๊ฒŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.. ์ด ๋ชจ๋“  ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ—˜ํ•ด ๋ณด์‹ญ์‹œ์˜ค.

 

๊ฒฐ๋ก ์ ์œผ๋กœ, ์ €๋Š” ๋‹น์‹ ์ด ๊ฐ€๋Šฅํ•  ๋•Œ๋งˆ๋‹ค ๋ฏธ๋ฆฌ ๊ณ„์‚ฐ๋œ ๋ผ์ดํŠธ๋งต์„ ๊ณ ์ˆ˜ํ•˜๊ณ , ๋™์  ๊ฐ์ฒด์—๋งŒ shadowmap์„ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‘ ๊ฐ€์ง€์˜ ์‹œ์ž‘์  ํ’ˆ์งˆ์ด ๋™์ผํ•œ์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค. ์™„๋ฒฝํ•œ ์ •์  ํ™˜๊ฒฝ๊ณผ ๋ชจ์–‘์ƒˆ๊ฐ€ ์ข‹์ง€ ์•Š์€ ๊ทธ๋ฆผ์ž๊ฐ€ ์žˆ๋Š” ๊ฒƒ๋„ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

 

 

 

๋ฐ˜์‘ํ˜•
728x90

์›๋ณธ - https://learnopengl.com/Getting-started/Creating-a-window

 

๋ฉ‹์ง„ ๊ทธ๋ž˜ํ”ฝ์„ ๋งŒ๋“ค๊ธฐ ์ „์— ๋จผ์ € ํ•ด์•ผ ํ•  ์ผ์€ OpenGL ์ปจํ…์ŠคํŠธ์™€ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฐฝ์„ ๋งŒ๋“ค์–ด์„œ ๋Œ์–ด์˜ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ด๋Ÿฌํ•œ ์ž‘์—…์€ ์šด์˜ ์ฒด์ œ๋งˆ๋‹ค ๋‹ค๋ฅด๋ฉฐ OpenGL์€ ์˜๋„์ ์œผ๋กœ ์ด๋Ÿฌํ•œ ์ž‘์—…์—์„œ ์ถ”์ƒํ™”ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, ์ฐฝ์„ ๋งŒ๋“ค๊ณ , ์ปจํ…์ŠคํŠธ๋ฅผ ์ •์˜ํ•˜๊ณ , ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ง์ ‘ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋‹คํ–‰ํžˆ๋„, ์šฐ๋ฆฌ๊ฐ€ ์ฐพ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๊ฝค ๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ผ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ํŠนํžˆ OpenGL์„ ๋ชฉํ‘œ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์šด์˜ ์ฒด์ œ๋ณ„ ์ž‘์—…์„ ๋ชจ๋‘ ์ €์žฅํ•˜๊ณ  ๋ Œ๋”๋งํ•  ์ˆ˜ ์žˆ๋Š” ์ฐฝ๊ณผ OpenGL ์ปจํ…์ŠคํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

GLUT, SDL, SFML, GLFW ๋“ฑ์ด ์œ ๋ช…ํ•ฉ๋‹ˆ๋‹ค.

LearnOpenGL์—์„œ๋Š” GLFW๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ์„ค์ •์€ GLFW์˜ ์„ค์ •๊ณผ ์œ ์‚ฌํ•˜๋ฏ€๋กœ ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

 

GLFW

GLFW๋Š” C๋กœ ์ž‘์„ฑ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ํŠนํžˆ OpenGL์„ ๋Œ€์ƒ์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค.

GLFW๋Š” ํ™”๋ฉด์— ์ƒํ’ˆ์„ ๋ Œ๋”๋งํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ํ•„์ˆ˜ํ’ˆ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด OpenGL ์ปจํ…์ŠคํŠธ๋ฅผ ๋งŒ๋“ค๊ณ , ์ฐฝ ๋งค๊ฐœ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ , ์‚ฌ์šฉ์ž ์ž…๋ ฅ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์šฐ๋ฆฌ์˜ ๋ชฉ์ ์— ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.

 

์ด ์žฅ๊ณผ ๋‹ค์Œ ์žฅ์˜ ์ถ”์ ์€ GLFW๋ฅผ ๊ฐ€๋™ํ•˜์—ฌ OpenGL ์ปจํ…์ŠคํŠธ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์ƒ์„ฑํ•˜๊ณ  ์šฐ๋ฆฌ๊ฐ€ ์žฅ๋‚œ์น  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ์ฐฝ์„ ํ‘œ์‹œํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ฐฝ์—์„œ๋Š” GLFW ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฒ€์ƒ‰, ๊ตฌ์ถ• ๋ฐ ์—ฐ๊ฒฐํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ์ ‘๊ทผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์„œ์—์„œ๋Š” Microsoft Visual Studio 2019 IDE๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค(๋” ์ตœ์‹  Visual Studio ๋ฒ„์ „์—์„œ๋„ ํ”„๋กœ์„ธ์Šค๋Š” ๋™์ผํ•ฉ๋‹ˆ๋‹ค).

Visual Studio(๋˜๋Š” ์ด์ „ ๋ฒ„์ „)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ IDE์—์„œ๋„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

 

GLFW ๋นŒ๋“œํ•˜๊ธฐ

GLFW๋Š” ์›น ํŽ˜์ด์ง€์˜ ๋‹ค์šด๋กœ๋“œ ํŽ˜์ด์ง€์—์„œ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

GLFW๋Š” ์ด๋ฏธ 2019๋…„๊นŒ์ง€ Visual Studio 2012์šฉ์œผ๋กœ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋œ ์ด์ง„ํŒŒ์ผ๊ณผ ํ—ค๋” ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ, ์™„์ „์„ฑ์„ ์œ„ํ•ด ์†Œ์Šค ์ฝ”๋“œ์—์„œ GLFW๋ฅผ ์ง์ ‘ ์ปดํŒŒ์ผํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜คํ”ˆ ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ง์ ‘ ์ปดํŒŒ์ผํ•˜๋Š” ๊ณผ์ •์— ๋Œ€ํ•œ ๋Š๋‚Œ์„ ์ฃผ๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์†Œ์Šค ํŒจํ‚ค์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

1
๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ 64๋น„ํŠธ ์ด์ง„ ํŒŒ์ผ๋กœ ๋งŒ๋“ค ์˜ˆ์ •์ด๋ฏ€๋กœ ์‚ฌ์ „ ์ปดํŒŒ์ผ๋œ ์ด์ง„ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ 64๋น„ํŠธ ์ด์ง„ ํŒŒ์ผ์„
๊ฐ€์ ธ์™€์•ผํ•ฉ๋‹ˆ๋‹ค.
cs

 

์†Œ์Šค ํŒจํ‚ค์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•œ ํ›„ ์••์ถœ์„ ํ’€๊ณ  ๋‚ด์šฉ์„ ์—ฝ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋ช‡ ๊ฐ€์ง€ ํ’ˆ๋ชฉ์—๋งŒ ์ง‘์ค‘ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  • ์ปดํŒŒ์ผ์˜ ๊ฒฐ๊ณผ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • include ํด๋”

์†Œ์Šค ์ฝ”๋“œ์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ปดํŒŒ์ผํ•˜๋ฉด ๊ฒฐ๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ CPU/OS์— ์™„๋ฒฝํ•˜๊ฒŒ ๋งž์ถคํ™”๋˜์–ด ๊ณ ๊ธ‰ ์‚ฌ์ „ ์ปดํŒŒ์ผ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ๊ฐ€ ํ•ญ์ƒ ์ œ๊ณต๋˜๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค(์‹œ์Šคํ…œ์—์„œ ์‚ฌ์ „ ์ปดํŒŒ์ผ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ๋„ ์žˆ์Œ).

๊ทธ๋Ÿฌ๋‚˜ ์˜คํ”ˆ ์›”๋“œ์— ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•  ๋•Œ์˜ ๋ฌธ์ œ๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ž์‹ ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๊ธฐ ์œ„ํ•ด ๋™์ผํ•œ IDE ๋˜๋Š” ๋นŒ๋“œ ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ฆ‰, ์ œ๊ณต๋œ ํ”„๋กœ์ ํŠธ/์†”๋ฃจ์…˜ ํŒŒ์ผ์ด ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž์˜ ์„ค์ •๊ณผ ํ˜ธํ™˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž๋Š” ์ง€์ •๋œ .c .cpp ๋ฐ .h .hpp ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž์‹ ๋งŒ์˜ ํ”„๋กœ์ ํŠธ/์†”๋ฃจ์…˜์„ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Š” ๋ฒˆ๊ฑฐ๋Ÿฌ์šด ์ž‘์—…์ž…๋‹ˆ๋‹ค.

๋ฐ”๋กœ ์ด๋Ÿฌํ•œ ์ด์œ ๋กœ Cmake๋ผ๋Š” ๋„๊ตฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

CMake

CMake๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ CMake ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†Œ์Šค ์ฝ”๋“œ ํŒŒ์ผ ๋ชจ์Œ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ํ”„๋กœ์ ํŠธ/์†”๋ฃจ์…˜ ํŒŒ์ผ(์˜ˆ: Visual Studio, ์ฝ”๋“œ::๋ธ”๋Ÿญ, Eclipse)์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” GLFW์˜ ์†Œ์Šค ํŒจํ‚ค์ง€์—์„œ Visual Studio 2019 ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ๋‹ค์šด๋กœ๋“œ ํŽ˜์ด์ง€์—์„œ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋Š” CMake๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜์—ฌ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

CMake๊ฐ€ ์„ค์น˜๋˜๋ฉด ๋ช…๋ น์ค„ ๋˜๋Š” GUI๋ฅผ ํ†ตํ•ด  CMake๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„ˆ๋ฌด ๋ณต์žกํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— GUI๋ฅผ ์‚ฌ์šฉํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

CMake์—๋Š” ์ด์ง„ ํŒŒ์ผ์— ๋Œ€ํ•œ ์†Œ์Šค ์ฝ”๋“œ ํด๋”์™€ ๋Œ€์ƒ ํด๋”๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์†Œ์Šค ์ฝ”๋“œ ํด๋”์˜ ๊ฒฝ์šฐ ๋‹ค์šด๋กœ๋“œํ•œ GLFW ์†Œ์Šค ํŒจํ‚ค์ง€์˜ ๋ฃจํŠธ ํด๋”๋ฅผ ์„ ํƒํ•˜๊ณ  ๋นŒ๋“œ ํด๋”์˜ ๊ฒฝ์šฐ ์ƒˆ ๋””๋ ‰ํ† ๋ฆฌ ๋นŒ๋“œ๋ฅผ ๋งŒ๋“  ๋‹ค์Œ ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค.

 

 

์†Œ์Šค ๋ฐ ๋Œ€์ƒ ํด๋”๋ฅผ ์„ค์ •ํ–ˆ์œผ๋ฉด ๊ตฌ์„ฑ ๋‹จ์ถ”๋ฅผ ํด๋ฆญํ•˜์—ฌ CMake๊ฐ€ ํ•„์š”ํ•œ ์„ค์ •๊ณผ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ํ”„๋กœ์ ํŠธ์˜ ์ƒ์„ฑ์ž๋ฅผ ์„ ํƒํ•ด์•ผ ํ•˜๋ฉฐ Visual Studio 2019๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— Visual Studio 16 ์˜ต์…˜์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค(Visual Studio 2019๋Š” Visual Studio 16์œผ๋กœ๋„ ์•Œ๋ ค์ ธ ์žˆ์Šต๋‹ˆ๋‹ค).

๊ทธ๋Ÿฐ ๋‹ค์Œ CMake๋Š” ๊ฒฐ๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€๋Šฅํ•œ ๋นŒ๋“œ ์˜ต์…˜์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์„ค์ •์„ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์œ ์ง€ํ•˜๊ณ  ๊ตฌ์„ฑ์„ ๋‹ค์‹œ ํด๋ฆญํ•˜์—ฌ ์„ค์ •์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์…‹ํŒ…์ด ์„ค์ •๋˜๋ฉด ์ƒ์„ฑ์„ ํด๋ฆญํ•˜๋ฉด ๊ฒฐ๊ณผ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์ด ๋นŒ๋“œ ํด๋”์— ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค.

 

Compilation(๋ชจ์Œ์ง‘)

๋นŒ๋“œ ํด๋”์—์„œ GLFW.sin ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ Visual Studio 2019์—์„œ ์—ฝ๋‹ˆ๋‹ค.

CMake๋Š” ์ด๋ฏธ ์ ์ ˆํ•œ ๊ตฌ์„ฑ ์„ค์ •์ด ํฌํ•จ๋œ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์„ ์ƒ์„ฑํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์†”๋ฃจ์…˜์„ ๊ตฌ์ถ•ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

CMake๋Š” 64๋น„ํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ๋„๋ก ์†”๋ฃจ์…˜์„ ์ž๋™์œผ๋กœ ๊ตฌ์„ฑํ–ˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋นŒ๋“œ ์†”๋ฃจ์…˜์„ ์„ ํƒํ•˜์‹ญ์‹œ์˜ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด glfw3.lib๋ผ๋Š” ์ด๋ฆ„์˜ build/src/debug ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ์ปดํŒŒ์ผ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

 

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•œ ํ›„์—๋Š” IDE๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ OpenGL ํ”„๋กœ๊ทธ๋žจ์˜ ํฌํ•จ ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ์œ„์น˜๋ฅผ ์•Œ๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด ์ž‘์—…์—๋Š” ๋‘ ๊ฐ€์ง€ ์ผ๋ฐ˜์ ์ธ ์ ‘๊ทผ ๋ฐฉ์‹์ด ์žˆ์Šต๋‹ˆ๋‹ค:

 

  1. IDE/์ปดํŒŒ์ผ๋Ÿฌ์—์„œ /lib ์™€ /include ํด๋”๋ฅผ ์ฐพ์•„์„œ GLFW์˜ include ํด๋”์˜ ๋‚ด์šฉ์„ IDE์˜ /include ํด๋”์— ์ถ”๊ฐ€ํ•˜๊ณ  ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ glfw3.lib๋ฅผ IDE์˜ /lib ํด๋”์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ํšจ๊ณผ๊ฐ€ ์žˆ์ง€๋งŒ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”์ ํ•˜๊ณ  ํŒŒ์ผ์„ ํฌํ•จํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต๊ณ  IDE/์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์ƒˆ๋กœ ์„ค์น˜ํ•˜๋ฉด ์ด ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋‹ค์‹œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•์€ IDE/compiler ์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋ชจ๋“  header files/libraries๋ฅผ ํฌํ•จํ•˜๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ ์„ธํŠธ๋ฅผ ์›ํ•˜๋Š” ์œ„์น˜์— ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด OpenGL ํ”„๋กœ์ ํŠธ์˜ ๋ชจ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ํ—ค๋” ํŒŒ์ผ์„ ๊ฐ๊ฐ ์ €์žฅํ•˜๋Š” Libs ๋ฐ Include ํด๋”๊ฐ€ ํฌํ•จ๋œ ๋‹จ์ผ ํด๋”๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ๋ชจ๋“  ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๋‹จ์ผ ์œ„์น˜(์—ฌ๋Ÿฌ ์ปดํ“จํ„ฐ์—์„œ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Œ) ๋‚ด์— ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค IDE์— ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š” ์œ„์น˜๋ฅผ ์•Œ๋ ค์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ•„์š”ํ•œ ํŒŒ์ผ์ด ์›ํ•˜๋Š” ์œ„์น˜์— ์ €์žฅ๋˜๋ฉด ์ฒซ ๋ฒˆ์งธ OpenGL GLFW ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์šฐ๋ฆฌ์˜ ์ฒซ๋ฒˆ์งธ ํ”„๋กœ์ ํŠธ

๋จผ์ € Visual Studio๋ฅผ ์—ด๊ณ  ์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์˜ต์…˜์ด ์ง€์ •๋œ ๊ฒฝ์šฐ C++๋ฅผ ์„ ํƒํ•˜๊ณ  ๋นˆ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค(ํ”„๋กœ์ ํŠธ์— ์ ํ•ฉํ•œ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์‹ญ์‹œ์˜ค). 64๋น„ํŠธ๋กœ ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์˜ˆ์ •์ด๋ฉฐ ํ”„๋กœ์ ํŠธ์˜ ๊ธฐ๋ณธ๊ฐ’์€ 32๋น„ํŠธ์ด๋ฏ€๋กœ ์ƒ๋‹จ์˜ ๋””๋ฒ„๊ทธ ์˜†์— ์žˆ๋Š” ๋“œ๋กญ๋‹ค์šด์„ x86์—์„œ x64๋กœ ๋ณ€๊ฒฝํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์ด ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ์ตœ์ดˆ์˜ OpenGL ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ž‘์—… ๊ณต๊ฐ„์„ ํ™•๋ณดํ•  ์ˆ˜  ์žˆ์Šต๋‹ˆ๋‹ค!

๋งํ‚น

ํ”„๋กœ์ ํŠธ๊ฐ€ GLFW๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์šฐ๋ฆฌ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์—ฐ๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ง์ปค ์„ค์ •์—์„œ glfw3.lib๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์„ ์ง€์ •ํ•จ์œผ๋กœ์จ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ํƒ€์‚ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค๋ฅธ ๋””๋ ‰ํ† ๋ฆฌ์— ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ๋Š” glfw3.lib๋ฅผ ์–ด๋””์„œ ์ฐพ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์•„์ง ๋ชจ๋ฆ…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋จผ์ € ์ด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

IDE๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ๊ณ  ํŒŒ์ผ์„ ํฌํ•จํ•ด์•ผ ํ•  ๋•Œ ์ด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๊ณ ๋ คํ•˜๋„๋ก ์ง€์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์†”๋ฃจ์…˜ ํƒ์ƒ‰๊ธฐ์—์„œ ํ”„๋กœ์ ํŠธ ์ด๋ฆ„์„ ๋งˆ์šฐ์Šค ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ์œผ๋กœ ํด๋ฆญํ•œ ๋‹ค์Œ ์•„๋ž˜ ์ด๋ฏธ์ง€์™€ ๊ฐ™์ด VC++ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ ๋‹ค์Œ ์‚ฌ์šฉ์ž ์ž์‹ ์˜ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๊ฐ€ ๊ฒ€์ƒ‰ํ•  ์œ„์น˜๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…์ŠคํŠธ์— ์ˆ˜๋™์œผ๋กœ ์‚ฝ์ž…ํ•˜๊ฑฐ๋‚˜ ์ ์ ˆํ•œ ์œ„์น˜ ๋ฌธ์ž์—ด์„ ํด๋ฆญํ•˜๊ณ  <ํŽธ์ง‘> ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋””๋ ‰ํ† ๋ฆฌ์™€ ํฌํ•จ ๋””๋ ‰ํ† ๋ฆฌ ๋ชจ๋‘์— ๋Œ€ํ•ด ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

์—ฌ๊ธฐ์„œ ์›ํ•˜๋Š” ๋งŒํผ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋•Œ๋ถ€ํ„ฐ IDE๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ํ—ค๋” ํŒŒ์ผ์„ ๊ฒ€์ƒ‰ํ•  ๋•Œ ํ•ด๋‹น ๋””๋ ‰ํ„ฐ๋ฆฌ๋„ ๊ฒ€์ƒ‰ํ•ฉ๋‹ˆ๋‹ค. GLFW์˜ Include ํด๋”๊ฐ€ ํฌํ•จ๋˜๋Š” ์ฆ‰์‹œ <GLFW/..>๋ฅผ ํฌํ•จํ•˜์—ฌ GLFW์˜ ๋ชจ๋“  ํ—ค๋” ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋””๋ ‰ํ† ๋ฆฌ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

VS๊ฐ€ ์ด์ œ ํ•„์š”ํ•œ ๋ชจ๋“  ํŒŒ์ผ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ Linker ํƒญ์œผ๋กœ ์ด๋™ํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž…๋ ฅํ•˜๋ฉด GLFW๋ฅผ ํ”„๋กœ์ ํŠธ์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์—ฐ๊ฒฐํ•˜๋ ค๋ฉด ๋ง์ปค์— ๋Œ€ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„์„ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„์ด glfw3.lib์ด๋ฏ€๋กœ ์ด๋ฅผ Additional Dependencies ํ•„๋“œ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค(์ˆ˜๋™ ๋˜๋Š” <Edit> ์˜ต์…˜ ์‚ฌ์šฉ) ๊ทธ๋ฆฌ๊ณ  ๊ทธ ์‹œ์ ๋ถ€ํ„ฐ ์šฐ๋ฆฌ๊ฐ€ ์ปดํŒŒ์ผํ•  ๋•Œ GLFW๊ฐ€ ์—ฐ๊ฒฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. GLFW ์™ธ์—๋„ OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋งํฌ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•˜์ง€๋งŒ ์šด์˜ ์ฒด์ œ์— ๋”ฐ๋ผ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Windows์—์„œ์˜ OpenGL

Windows์—์„œ OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ opengl32.lib๋Š” Visual Studio๋ฅผ ์„ค์น˜ํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์„ค์น˜ํ•  ๋•Œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์„ค์น˜๋˜๋Š” Microsoft SDK์™€ ํ•จ๊ป˜ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. ์ด ์žฅ์—์„œ๋Š” VS ์ปดํŒŒ์ผ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์œˆ๋„์šฐ์— ์žˆ์œผ๋ฏ€๋กœ ๋ง์ปค ์„ค์ •์— opengl32.lib๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ 64๋น„ํŠธ ๋“ฑ๊ฐ€๋Š” 32๋น„ํŠธ ๋“ฑ๊ฐ€์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ opengl32.lib๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

 

Linux์—์„œ์˜ OpenGL

Linux ์‹œ์Šคํ…œ์—์„œ๋Š” ๋ง์ปค ์„ค์ •์— -IGL์„ ์ถ”๊ฐ€ํ•˜์—ฌ libGL.so ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์—ฐ๊ฒฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ Mesa, NVidia ๋˜๋Š” AMD dev ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ GLFW ๋ฐ OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋ชจ๋‘ ๋ง์ปค ์„ค์ •์— ์ถ”๊ฐ€ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด GLFW์˜ ํ—ค๋” ํŒŒ์ผ์„ ํฌํ•จ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
#include <GLFW/glfw3.h>
cs
1
GCC๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ปดํŒŒ์ผํ•˜๋Š” Linux ์‚ฌ์šฉ์ž์˜ ๊ฒฝ์šฐ ํ”„๋กœ์ ํŠธ๋ฅผ ์ปดํŒŒ์ผํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๋ช…๋ น์ค„ ์˜ต์…˜์€
lglfw3 -IGL -IX11 -lpthread -IXr -IXi -ldl์ž…๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์—ฐ๊ฒฐํ•˜์ง€ ์•Š์œผ๋ฉด
์ •์˜๋˜์ง€ ์•Š์€ ์ฐธ์กฐ ์˜ค๋ฅ˜๊ฐ€ ๋งŽ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
cs

์ด๊ฒƒ์œผ๋กœ GLFW์˜ ์„ค์ • ๋ฐ ๊ตฌ์„ฑ์ด ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

GLAD

์•„์ง ํ•œ ๊ฐ€์ง€ ๋” ํ•ด์•ผ ํ•  ์ผ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์•„์ง ๊ฑฐ๊ธฐ๊นŒ์ง€๋Š” ์ด๋ฅด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. OpenGL์€ ์‹ค์ œ๋กœ ํ‘œ์ค€/์‚ฌ์–‘์— ๋ถˆ๊ณผํ•˜๋ฏ€๋กœ ํŠน์ • ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ๊ฐ€ ์ง€์›ํ•˜๋Š” ๋“œ๋ผ์ด๋ฒ„์— ์ด ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๋“œ๋ผ์ด๋ฒ„ ์ œ์กฐ์—…์ฒด์— ๋‹ฌ๋ ค ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์–‘ํ•œ ๋ฒ„์ „์˜ OpenGL ๋“œ๋ผ์ด๋ฒ„๊ฐ€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ์‹œ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ ์œ„์น˜๋ฅผ ์•Œ ์ˆ˜ ์—†์œผ๋ฉฐ ๋Ÿฐํƒ€์ž„์— ์ฟผ๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ํ•„์š”ํ•œ ๊ธฐ๋Šฅ์˜ ์œ„์น˜๋ฅผ ๊ฒ€์ƒ‰ํ•˜์—ฌ ๋‚˜์ค‘์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋Šฅ ํฌ์ธํ„ฐ์— ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ๊ฐœ๋ฐœ์ž์˜ ์ž‘์—…์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์œ„์น˜ ๊ฒ€์ƒ‰์€ OS๋ณ„๋กœ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. Windows์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
// define the function's prototype
typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);
// find the function and assign it to a function pointer
GL_GENBUFFERS glGenBuffers  = (GL_GENBUFFERS)wglGetProcAddress("glGenBuffers");
// function can now be called as normal
unsigned int buffer;
glGenBuffers(1&buffer);
cs

์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด ๋ณด์ด๊ณ  ์•„์ง ์„ ์–ธ๋˜์ง€ ์•Š์€ ๊ฐ ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์€ ๋ฒˆ๊ฑฐ๋Ÿฌ์šด ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•˜๊ฒŒ๋„, GLAD์™€ ๊ฐ™์ด ์ธ๊ธฐ ์žˆ๊ณ  ์ตœ์‹ ์ธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

GLAD ์„ค์ •ํ•˜๊ธฐ

GLAD๋Š” ์šฐ๋ฆฌ๊ฐ€ ์ด์•ผ๊ธฐํ•œ ๋ชจ๋“  ๋ฒˆ๊ฑฐ๋Ÿฌ์šด ์ž‘์—…์„ ๊ด€๋ฆฌํ•˜๋Š” ์˜คํ”ˆ ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค. GLAD๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์ผ๋ฐ˜์ ์ธ ์˜คํ”ˆ ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์•ฝ๊ฐ„ ๋‹ค๋ฅธ ๊ตฌ์„ฑ ์„ค์ •์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. GLAD๋Š” ์–ด๋–ค ๋ฒ„์ „์˜ OpenGL์— ๋Œ€ํ•ด ํ•ด๋‹น ๋ฒ„์ „์— ๋”ฐ๋ผ ๋ชจ๋“  ๊ด€๋ จ OpenGL ๊ธฐ๋Šฅ์„ ์ •์˜ํ•˜๊ณ  ๋กœ๋“œํ•  ๊ฒƒ์ธ์ง€๋ฅผ GLAD์— ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ๋Š” ์›น ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

GLAD ์›น ์„œ๋น„์Šค๋กœ ์ด๋™ํ•˜์—ฌ ์–ธ์–ด๊ฐ€ C++๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  API ์„น์…˜์—์„œ 3.3์ด์ƒ์˜ OpenGL ๋ฒ„์ „์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํ”„๋กœํŒŒ์ผ์ด Core๋กœ ์„ค์ •๋˜์–ด ์žˆ๊ณ  Generate a loader ์˜ต์…˜์ด ์„ ํƒ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

ํ™•์žฅ๋ช…์„ ๋ฌด์‹œํ•˜๊ณ  ์ƒ์„ฑ์„ ํด๋ฆญํ•˜์—ฌ ๊ฒฐ๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ง€๊ธˆ์ฏค GLAD๋Š” ๋‘ ๊ฐœ์˜ ํฌํ•จ ํด๋”๊ฐ€ ํฌํ•จ๋œ zip ํŒŒ์ผ๊ณผ ํ•˜๋‚˜์˜ glad.c ํŒŒ์ผ์„ ์ œ๊ณตํ–ˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํฌํ•จ ํด๋”(glad ๋ฐ KHR)๋ฅผ ๋ชจ๋‘ ํฌํ•จ ๋””๋ ‰ํ„ฐ๋ฆฌ์— ๋ณต์‚ฌํ•˜๊ณ (๋˜๋Š” ์ด ํด๋”๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค) glad.c ํŒŒ์ผ์„ ํ”„๋กœ์ ํŠธ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ด์ „ ๋‹จ๊ณ„๋ฅผ ์ˆ˜ํ–‰ํ•œ ํ›„์—๋Š” ํŒŒ์ผ ์œ„์— ๋‹ค์Œ ํฌํ•จ ์ง€์‹œ๋ฌธ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
#include <glad/glad.h> 
cs

์ปดํŒŒ์ผ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ๋„ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋‹ค์Œ ์žฅ์—์„œ GLFW์™€ GLAD๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ OpenGL ์ปจํ…์ŠคํŠธ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ  ์ฐฝ์„ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. ํฌํ•จ ๋ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ๋ชจ๋‘ ์˜ฌ๋ฐ”๋ฅด๊ณ  ๋ง์ปค ์„ค์ •์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ด๋ฆ„์ด ํ•ด๋‹น ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

 

 

๋ฐ˜์‘ํ˜•
728x90

์›๋ณธ - https://learnopengl.com/Getting-started/OpenGL

 

์—ฌ์ •์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๋จผ์ € OpenGL์ด ์‹ค์ œ๋กœ ๋ฌด์—‡์ธ์ง€ ์ •์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

OpenGL์€ ์ฃผ๋กœ ๊ทธ๋ž˜ํ”ฝ๊ณผ ์ด๋ฏธ์ง€๋ฅผ ์กฐ์ž‘ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” API(Application Programming Interface)๋กœ์จ ํ›„๋ณด๋กœ ๊ฑฐ๋ก ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ OpenGL ์ž์ฒด๋Š” API๊ฐ€ ์•„๋‹ˆ๋ผ ํฌ๋กœ๋…ธ์Šค ๊ทธ๋ฃน์ด ๊ฐœ๋ฐœํ•˜๊ณ  ์œ ์ง€ ๊ด€๋ฆฌํ•˜๋Š” ์‚ฌ์–‘์— ๋ถˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

 

OpenGL ์‚ฌ์–‘์€ ๊ฐ ๊ธฐ๋Šฅ์˜ ๊ฒฐ๊ณผ/์ถœ๋ ฅ๊ณผ ์ˆ˜ํ–‰ ๋ฐฉ๋ฒ•์„ ์ •ํ™•ํ•˜๊ฒŒ ๋ช…์‹œํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ด ๊ธฐ๋Šฅ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•ด์•ผ ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ๋งˆ๋ จํ•˜๋Š” ๊ฒƒ์€ ์ด ์‚ฌ์–‘์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋‹ฌ๋ ค์žˆ์Šต๋‹ˆ๋‹ค.

OpenGL ์‚ฌ์–‘์—๋Š” ๊ตฌํ˜„ ์„ธ๋ถ€ ์ •๋ณด์ด ๋‚˜์™€ ์žˆ์ง€ ์•Š์œผ๋ฏ€๋กœ, ์‹ค์ œ ๊ฐœ๋ฐœ๋œ OpenGL ๋ฒ„์ „์€ ๊ฒฐ๊ณผ๊ฐ€ ์‚ฌ์–‘๊ณผ ์ผ์น˜ํ•˜๋Š” ํ•œ(๋”ฐ๋ผ์„œ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋™์ผํ•œ) ๋‹ค๋ฅธ ๊ตฌํ˜„์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

์‹ค์ œ OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์€ ๋Œ€๊ฐœ ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ ์ œ์กฐ์—…์ฒด์ž…๋‹ˆ๋‹ค.

๊ตฌ์ž…ํ•œ ๊ฐ ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ๋Š” ํ•ด๋‹น ์นด๋“œ์šฉ ํŠน๋ณ„ํžˆ ๊ฐœ๋ฐœ๋œ OpenGL ๋ฒ„์ „์ธ ํŠน์ • OpenGL ๋ฒ„์ „์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

Apple ์‹œ์Šคํ…œ์„ ์‚ฌ์šฉํ•  ๋•Œ OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” Apple์ด ์ง์ ‘ ๊ด€๋ฆฌํ•˜๋ฉฐ Linux ์•„๋ž˜์—๋Š” ๊ทธ๋ž˜ํ”ฝ ๊ณต๊ธ‰์—…์ฒด์˜ ๋ฒ„์ „๊ณผ ์ด๋Ÿฌํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์• ํ˜ธ๊ฐ€์˜ ์ ์‘์ด ๊ฒฐํ•ฉ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Š” OpenGL์ด ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ์ด์ƒํ•œ ๋™์ž‘์„ ๋ณด์ผ ๋•Œ๋งˆ๋‹ค ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ ์ œ์กฐ์—…์ฒด(๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐœ๋ฐœ/์œ ์ง€ ๊ด€๋ฆฌํ•œ ์‚ฌ๋žŒ)์˜ ์ž˜๋ชป์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

1
๋Œ€๋ถ€๋ถ„์˜ ๊ตฌํ˜„์€ ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ ์ œ์กฐ์—…์ฒด์— ์˜ํ•ด ๊ตฌ์ถ•๋˜๋ฏ€๋กœ ๊ตฌํ˜„์— ๋ฒ„๊ทธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์ผ๋ฐ˜์ ์œผ๋กœ
๋น„๋””์˜ค ์นด๋“œ ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.
์ด๋Ÿฐ ๋“œ๋ผ์ด๋ฒ„์—๋Š” ์นด๋“œ์—์„œ ์ง€์›ํ•˜๋Š” ์ตœ์‹  ๋ฒ„์ „์˜ OpenGL์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜ํ”ฝ ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ๊ถŒ์žฅ๋˜๋Š” ์ด์œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.
cs

 

Khronos๋Š” ๋ชจ๋“  OpenGL ๋ฒ„์ „์— ๋Œ€ํ•œ ๋ชจ๋“  ์‚ฌ์–‘ ๋ฌธ์„œ๋ฅผ ๊ณต๊ฐœ์ ์œผ๋กœ ํ˜ธ์ŠคํŒ…ํ•ฉ๋‹ˆ๋‹ค.

๊ด€์‹ฌ ์žˆ๋Š” ๋…์ž๋Š” ์—ฌ๊ธฐ์—์„œ ๋ฒ„์ „ 3.3์˜ OpenGL ์‚ฌ์–‘(์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ๋ฒ„์ „)์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์‚ฌ์–‘์€ OpenGL์˜ ์„ธ๋ถ€ ์‚ฌํ•ญ์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ์ข‹์€ ์ฝ์„๊ฑฐ๋ฆฌ์ž…๋‹ˆ๋‹ค(๊ตฌํ˜„์ด ์•„๋‹Œ ๊ฒฐ๊ณผ๋งŒ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค).

๋˜ํ•œ ์‚ฌ์–‘์€ ๊ธฐ๋Šฅ์˜ ์ •ํ™•ํ•œ ์ž‘๋™์„ ์ฐพ๋Š”๋ฐ ์œ ์šฉํ•œ ์ฐธ๊ณ  ์ž๋ฃŒ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

์ฝ”์–ด ํ”„๋กœํŒŒ์ผ vs ์ฆ‰์‹œ ๋ชจ๋“œ(๊ณ ์ • ํ•จ์ˆ˜ ํŒŒ์ดํ”„๋ผ์ธ)

์˜›๋‚ ์—๋Š” OpenGL์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ๊ทธ๋ž˜ํ”ฝ์„ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•œ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ๋ฐฉ๋ฒ•์ธ ์ฆ‰์‹œ ๋ชจ๋“œ(๊ณ ์ • ํ•จ์ˆ˜ ํŒŒ์ดํ”„๋ผ์ธ์ด๋ผ๊ณ ๋„ ํ•จ)๋กœ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ–ˆ์Šต๋‹ˆ๋‹ค.

OpenGL์˜ ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์•ˆ์— ์ˆจ๊ฒจ์ ธ ์žˆ์—ˆ๊ณ  ๊ฐœ๋ฐœ์ž๋“ค์€ OpenGL์ด ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ์‹์„ ํฌ๊ฒŒ ํ†ต์ œํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋ฐœ์ž๋“ค์€ ๊ฒฐ๊ตญ ๋” ๋งŽ์€ ์œ ์—ฐ์„ฑ์„ ์›ํ–ˆ๊ณ , ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ์‚ฌ์–‘์ด ๋” ์œ ์—ฐํ•ด์กŒ๊ณ , ๊ฐœ๋ฐœ์ž๋“ค์€ ๊ทธ๋“ค์˜ ๊ทธ๋ž˜ํ”ฝ์„ ๋” ๋งŽ์ด ํ†ต์ œํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

๊ณ ์ • ํ•จ์ˆ˜ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์ •๋ง ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ  ์ดํ•ดํ•˜๊ธฐ ์‰ฝ์ง€๋งŒ, ๋˜ํ•œ ๋งค์šฐ ๋น„ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ ๋กœ ์ด ์‚ฌ์–‘์€ ๋ฒ„์ „ 3.2 ์ดํ›„ ์ฆ‰์‹œ ๋ชจ๋“œ ๊ธฐ๋Šฅ์„ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ ์‹œ์ž‘ํ–ˆ์œผ๋ฉฐ ๊ฐœ๋ฐœ์ž๋“ค์ด OpenGL์˜ ์ฝ”์–ด ํ”„๋กœํŒŒ์ผ ๋ชจ๋“œ๋กœ ๊ฐœ๋ฐœํ•˜๋„๋ก ๋™๊ธฐ๋ฅผ ๋ถ€์—ฌํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ชจ๋“œ๋Š” ์˜ค๋ž˜๋œ ๋ชจ๋“  ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ฑฐํ•œ OpenGL์˜ ์‚ฌ์–‘์˜ ํ•œ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค.

 

OpenGL์˜ ํ•ต์‹ฌ ํ”„๋กœํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ๋•Œ OpenGL์€ ํ˜„๋Œ€์  ๊ด€ํ–‰์„ ์‚ฌ์šฉํ•˜๋„๋ก ๊ฐ•์š”ํ•ฉ๋‹ˆ๋‹ค.

OpenGL์—์„œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ํ•จ์ˆ˜ ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•  ๋•Œ๋งˆ๋‹ค OpenGL์—์„œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ๊ทธ๋ฆฌ๊ธฐ๊ฐ€ ์ค‘์ง€๋ฉ๋‹ˆ๋‹ค.

ํ˜„๋Œ€์ ์ธ ์ ‘๊ทผ๋ฒ•์„ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์˜ ์žฅ์ ์€ ๊ทธ๊ฒƒ์ด ๋งค์šฐ ์œ ์—ฐํ•˜๊ณ  ํšจ์œจ์ ์ด๋ผ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ๊ทธ๊ฒƒ์€ ๋˜ํ•œ ๋ฐฐ์šฐ๊ธฐ๊ฐ€ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ๊ณ ์ • ํ•จ์ˆ˜ ํŒŒ์ดํ”„๋ผ์ธ์€ OpenGL์ด ์ˆ˜ํ–‰ํ•œ ์‹ค์ œ ์ž‘์—…์—์„œ ์ƒ๋‹นํžˆ ๋งŽ์€ ๋ถ€๋ถ„์„ ์ถ”์ƒํ™”ํ–ˆ์œผ๋ฉฐ ํ•™์Šตํ•˜๊ธฐ๋Š” ์‰ฌ์› ์ง€๋งŒ ์‹ค์ œ๋กœ OpenGL์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ๋Š” ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค.

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

 

์ด๊ฒƒ์€ ๋˜ํ•œ ์ด ์ฑ…์ด ํ•ต์‹ฌ ํ”„๋กœํ•„ OpenGL ๋ฒ„์ „ 3.3์— ๋งž์ถฐ์ง„ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๋น„๋ก ๊ทธ๊ฒƒ์ด ๋” ์–ด๋ ต์ง€๋งŒ, ๊ทธ๊ฒƒ์€ ๋…ธ๋ ฅํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ˜„์žฌ OpenGL 4.6์„ ์ž‘์„ฑํ•˜๋Š” ์‹œ์ ์—์„œ ์ƒ์œ„ ๋ฒ„์ „์˜ OpenGL์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

OpenGL 4.6์ด ์ถœ์‹œ๋œ ์ƒํƒœ์—์„œ OpenGL 3.3์„ ์ œ๊ฐ€ ์„ ํƒํ•œ ์ด์œ ๋Š” ๋ฌด์—‡์ผ๊นŒ์š”?

๊ทธ ์งˆ๋ฌธ์— ๋Œ€ํ•œ ๋Œ€๋‹ต์€ ๋น„๊ต์  ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. 3.3 ์ดํ›„ ๋ฒ„์ „์˜ ๋ชจ๋“  OpenGL์€ OpenGL์˜ ํ•ต์‹ฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  OpenGL์— ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์ƒˆ๋กœ์šด ๋ฒ„์ „์€ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ์•ฝ๊ฐ„ ๋” ํšจ์œจ์ ์ด๊ฑฐ๋‚˜ ์œ ์šฉํ•œ ๋ฐฉ๋ฒ•์„ ๋„์ž…ํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.

๊ทธ ๊ฒฐ๊ณผ ๋ชจ๋“  ๊ฐœ๋…๊ณผ ๊ธฐ์ˆ ์ด ์ตœ์‹  OpenGL ๋ฒ„์ „์—์„œ ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋˜๋ฏ€๋กœ OpenGL 3.3์„ ํ•™์Šตํ•˜๋Š” ๊ฒƒ์ด ์™„๋ฒฝํ•˜๊ฒŒ ์œ ํšจํ•ฉ๋‹ˆ๋‹ค.

์–ธ์ œ๋“ ์ง€ ์ค€๋น„๊ฐ€ ๋˜์—ˆ๊ฑฐ๋‚˜ ๊ฒฝํ—˜์ด ํ’๋ถ€ํ•˜๋ฉด ์ตœ์‹  OpenGL ๋ฒ„์ „์˜ ํŠน์ • ๊ธฐ๋Šฅ์„ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1
์ตœ์‹  ๋ฒ„์ „์˜ OpenGL ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ตœ์‹  ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ๋งŒ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๊ฒƒ์ด ๋Œ€๋ถ€๋ถ„์˜ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ผ๋ฐ˜์ ์œผ๋กœ ๋‚ฎ์€ ๋ฒ„์ „์˜ OpenGL์„ ๋ชฉํ‘œ๋กœ ํ•˜๊ณ  ์„ ํƒ์ ์œผ๋กœ ๋” ๋†’์€ ๋ฒ„์ „์˜ ๊ธฐ๋Šฅ์„
๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค.
cs

์ผ๋ถ€ ์ฑ•ํ„ฐ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ธฐ๋ก๋œ ๋ณด๋‹ค ํ˜„๋Œ€์ ์ธ ๊ธฐ๋Šฅ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํ™•์žฅ

OpenGL์˜ ํฐ ํŠน์ง•์€ ํ™•์žฅ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜ํ”ฝ ํšŒ์‚ฌ์—์„œ ๋ Œ๋”๋ง์„ ์œ„ํ•œ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์ด๋‚˜ ์ƒˆ๋กœ์šด ๋Œ€๊ทœ๋ชจ ์ตœ์ ํ™”๋ฅผ ์ œ์•ˆํ•  ๋•Œ๋งˆ๋‹ค ๋“œ๋ผ์ด๋ฒ„์— ๊ตฌํ˜„๋œ ํ™•์žฅ ๊ธฐ๋Šฅ์—์„œ ์ข…์ข… ๋ฐœ๊ฒฌ๋ฉ๋‹ˆ๋‹ค.

์‘์šฉํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋˜๋Š” ํ•˜๋“œ์›จ์–ด๊ฐ€ ์ด๋Ÿฌํ•œ ํ™•์žฅ์„ ์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž๋Š” ํ™•์žฅ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณด๋‹ค ๊ณ ๊ธ‰ ๋˜๋Š” ํšจ์œจ์ ์ธ ๊ทธ๋ž˜ํ”ฝ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ทธ๋ž˜ํ”ฝ ๊ฐœ๋ฐœ์ž๋Š” ํ™•์žฅ ๊ธฐ๋Šฅ์ด ๊ทธ๋ž˜ํ”ฝ ์นด๋“œ์—์„œ ์ง€์›๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด OpenGL์ด ํ–ฅํ›„ ๋ฒ„์ „์— ๊ธฐ๋Šฅ์„ ํฌํ•จํ•  ๋–„๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ ๋„ ์ด๋Ÿฌํ•œ ์ƒˆ๋กœ์šด ๋ Œ๋”๋ง ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ข…์ข… ํ™•์žฅ์ด ์ธ๊ธฐ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ๋งค์šฐ ์œ ์šฉํ•œ ๊ฒฝ์šฐ ๋‚˜์ค‘์— OpenGL ๋ฒ„์ „์˜ ์ผ๋ถ€๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

๊ฐœ๋ฐœ์ž๋Š” ์ด๋Ÿฌํ•œ ํ™•์žฅ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „(๋˜๋Š” OpenGL ํ™•์žฅ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์ „) ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ํ™•์žฅ์ด ์žˆ๋Š”์ง€ ๋ฌธ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ํ†ตํ•ด ๊ฐœ๋ฐœ์ž๋Š” ํ™•์žฅ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์— ๋”ฐ๋ผ ๋” ๋‚˜์€ ์ž‘์—… ๋˜๋Š” ๋” ํšจ์œจ์ ์ธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1
2
3
4
5
6
7
8
if(GL_ARB_extension_name)
{
    // Do cool new and modern stuff supported by hardware
}
else
{
    // Extension not supported: do it the old way
}
 
cs

OpenGl ๋ฒ„์ „ 3.3์—์„œ๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ์ˆ ์„ ํ™•์žฅํ•  ํ•„์š”๊ฐ€ ๊ฑฐ์˜ ์—†์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ ์ ˆํ•œ ์ง€์นจ์ด ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค.

์ƒํƒœ ๋จธ์‹ 

OpenGL์€ ๊ทธ ์ž์ฒด๋กœ ๋Œ€๊ทœ๋ชจ ์ƒํƒœ ์‹œ์Šคํ…œ์œผ๋กœ, OpenGL์ด ํ˜„์žฌ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์„ ์ •์˜ํ•˜๋Š” ๋ณ€์ˆ˜ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค.

OpenGL์˜ ์ƒํƒœ๋ฅผ ์ผ๋ฐ˜์ ์œผ๋กœ OpenGL ์ปจํ…์ŠคํŠธ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. OpenGL์„ ์‚ฌ์šฉํ•  ๋•Œ ์ผ๋ถ€ ์˜ต์…˜์„ ์„ค์ •ํ•˜๊ณ  ๋ฒ„ํผ๋ฅผ ์กฐ์ž‘ํ•œ ๋‹ค์Œ ํ˜„์žฌ ์ปจํ…์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ Œ๋”๋งํ•˜์—ฌ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, OpenGL์ด ์‚ผ๊ฐํ˜• ๋Œ€์‹  ์„ ์„ ๊ทธ๋ฆฌ๊ณ  ์‹ถ๋‹ค๊ณ  ๋งํ•  ๋•Œ๋งˆ๋‹ค OpenGL์ด ๊ทธ๋ฆฌ๋Š” ๋ฐฉ๋ฒ•์„ ์„ค์ •ํ•˜๋Š” ์ผ๋ถ€ ์ปจํ…์ŠคํŠธ ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ  OpenGL์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค.

OpenGL์— ์„ ์„ ๊ทธ์–ด์•ผ ํ•œ๋‹ค๊ณ  ๋งํ•ด ์ปจํ…์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์ฆ‰์‹œ ๋‹ค์Œ ๊ทธ๋ฆฌ๊ธฐ ๋ช…๋ น์€ ์‚ผ๊ฐํ˜• ๋Œ€์‹  ์„ ์„ ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.

 

OpenGL์—์„œ ์ž‘์—…ํ•  ๋•Œ ์ปจํ…์ŠคํŠธ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ์—ฌ๋Ÿฌ ์ƒํƒœ ๋ณ€๊ฒฝ ๊ธฐ๋Šฅ๊ณผ OpenGL์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ผ๋ถ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์—ฌ๋Ÿฌ ์ƒํƒœ ์‚ฌ์šฉ ๊ธฐ๋Šฅ์„ ๋งŒ๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

OpenGL์ด ๊ธฐ๋ณธ์ ์œผ๋กœ ํ•˜๋‚˜์˜ ๋Œ€ํ˜• ์ƒํƒœ ์‹œ์Šคํ…œ์ด๋ผ๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜๋Š” ํ•œ, ๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์€ ๋” ์˜๋ฏธ๊ฐ€ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์˜ค๋ธŒ์ ํŠธ

OpenGL ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” C๋กœ ์ž‘์„ฑ๋˜์–ด ์žˆ์œผ๋ฉฐ ๋‹ค๋ฅธ ์–ธ์–ด๋กœ ๋งŽ์€ ํŒŒ์ƒ์„ ํ—ˆ์šฉํ•˜์ง€๋งŒ ํ•ต์‹ฌ์ ์œผ๋กœ๋Š” C๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค.

C ์–ธ์–ด ๊ตฌ์กฐ ์ค‘ ๋งŽ์€ ๋ถ€๋ถ„์ด ๋‹ค๋ฅธ ๊ณ ๊ธ‰ ์–ธ์–ด๋กœ ์ž˜ ๋ฒˆ์—ญ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— OpenGL์€  ๋ช‡ ๊ฐ€์ง€ ์ถ”์ƒํ™”๋ฅผ ์—ผ๋‘์— ๋‘๊ณ  ๊ฐœ๋ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ถ”์ƒํ™” ์ค‘ ํ•˜๋‚˜๋Š” OpenGL์˜ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

 

OpenGL์˜ ๊ฐœ์ฒด๋Š” OpenGL ์ƒํƒœ์˜ ํ•˜์œ„ ์ง‘ํ•ฉ์„ ๋‚˜ํƒ€๋‚ด๋Š” ์˜ต์…˜ ๋ชจ์Œ์ž…๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ๋„๋ฉด ์ฐฝ์˜ ์„ค์ •์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ์ฒด์˜ ํฌ๊ธฐ, ์ง€์›๋˜๋Š” ์ƒ‰์ƒ ์ˆ˜ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ฐ์ฒด์˜ ํฌ๊ธฐ, ์ง€์›๋˜๋Š” ์ƒ‰์ƒ ์ˆ˜ ๋“ฑ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌผ์ฒด๋ฅผ C์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋กœ ์‹œ๊ฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1
2
3
4
5
struct object_name {
    float  option1;
    int    option2;
    char[] name;
};
cs

๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•  ๋•Œ๋งˆ๋‹ค ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ž…๋‹ˆ๋‹ค(OpenGL์˜ ์ปจํ…์ŠคํŠธ๊ฐ€ ํฐ ๊ตฌ์กฐ๋กœ ์‹œ๊ฐํ™”๋จ)

 

1
2
3
4
5
6
// The State of OpenGL
struct OpenGL_Context {
      ...
      object_name* object_Window_Target;
      ...      
};
cs
1
2
3
4
5
6
7
8
9
10
// create object
unsigned int objectId = 0;
glGenObject(1&objectId);
// bind/assign object to context
glBindObject(GL_WINDOW_TARGET, objectId);
// set options of object currently bound to GL_WINDOW_TARGET
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_WIDTH,  800);
glSetObjectOption(GL_WINDOW_TARGET, GL_OPTION_WINDOW_HEIGHT, 600);
// set context target back to default
glBindObject(GL_WINDOW_TARGET, 0);
cs

 

์ด ์ž‘์€ ์ฝ”๋“œ ์กฐ๊ฐ์€ OpenGL๋กœ ์ž‘์—…ํ•  ๋•Œ ์ž์ฃผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์›Œํฌํ”Œ๋กœ์šฐ์ž…๋‹ˆ๋‹ค.

๋จผ์ € ๊ฐœ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ฐธ์กฐ๋ฅผ ID๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค(์‹ค์ œ ๊ฐœ์ฒด์˜ ๋ฐ์ดํ„ฐ๋Š” ์”ฌ ๋’ค์— ์ €์žฅ๋จ).

๊ทธ๋Ÿผ ๋‹ค์Œ ๊ฐœ์ฒด(ID ์‚ฌ์šฉ)๋ฅผ ์ปจํ…์ŠคํŠธ์˜ ๋Œ€์ƒ ์œ„์น˜์— ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค(์˜ˆ: ์ฐฝ ๊ฐœ์ฒด ๋Œ€์ƒ ์œ„์น˜๋Š” GL_WINDOW_TARGET์œผ๋กœ ์ •์˜๋จ).

๋‹ค์Œ์œผ๋กœ ์ฐฝ ์˜ต์…˜์„ ์„ค์ •ํ•˜๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ์ฐฝ ๋Œ€์ƒ์˜ ํ˜„์žฌ ๊ฐœ์ฒด ID๋ฅผ 0์œผ๋กœ ์„ค์ •ํ•˜์—ฌ ๊ฐœ์ฒด์˜ ๋ฐ”์ธ๋”ฉ์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.

์„ค์ •ํ•œ ์˜ต์…˜์€ objectId์—์„œ ์ฐธ์กฐํ•˜๋Š” ๊ฐœ์ฒด์— ์ €์žฅ๋˜๊ณ  ๊ฐœ์ฒด๋ฅผ GL_WINDOW_TARGET์— ๋‹ค์‹œ ๋ฐ”์ธ๋”ฉํ•˜๋Š” ์ฆ‰์‹œ ๋ณต์›๋ฉ๋‹ˆ๋‹ค.

 

1
์ง€๊ธˆ๊นŒ์ง€ ์ œ๊ณต๋œ ์ฝ”๋“œ ์ƒ˜ํ”Œ์€ OpenGL์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์— ๋Œ€ํ•œ ๊ทผ์‚ฌ์น˜์ผ ๋ฟ์ด๋ฉฐ, ์ฑ… ์ „์ฒด์—์„œ ์‹ค์ œ ์˜ˆ์ œ๋ฅผ ์ถฉ๋ถ„ํžˆ
๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
cs

 

์ด๋Ÿฌํ•œ ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋‘˜ ์ด์ƒ์˜ ๊ฐœ์ฒด๋ฅผ ์ •์˜ํ•˜๊ณ  ์˜ต์…˜์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ OpenGL์˜ ์ƒํƒœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ž‘์—…์„ ์‹œ์ž‘ํ•  ๋•Œ๋งˆ๋‹ค ์›ํ•˜๋Š” ์„ค์ •์œผ๋กœ ๊ฐœ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด 3D ๋ชจ๋ธ ๋ฐ์ดํ„ฐ(์ง‘ ๋˜๋Š” ์บ๋ฆญํ„ฐ)์˜ ์ปจํ…Œ์ด๋„ˆ ๊ฐœ์ฒด ์—ญํ• ์„ ํ•˜๋Š” ๊ฐœ์ฒด๊ฐ€ ์žˆ์œผ๋ฉฐ, ์ด ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ทธ๋ฆฌ๊ณ  ์‹ถ์„ ๋•Œ๋งˆ๋‹ค ์šฐ๋ฆฌ๋Š” ์šฐ๋ฆฌ๊ฐ€ ๊ทธ๋ฆด ๋ชจ๋ธ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด ์žˆ๋Š” ๊ฐœ์ฒด๋ฅผ ๋ฐ”์ธ๋”ฉํ•ฉ๋‹ˆ๋‹ค(์ด๋Ÿฌํ•œ ๊ฐœ์ฒด์— ๋Œ€ํ•œ ์˜ต์…˜์„ ๋จผ์ € ๋งŒ๋“ค๊ณ  ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค).

๊ฐ์ฒด๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ์œผ๋ฉด ๋งŽ์€ ๋ชจ๋ธ์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ณ  ํŠน์ • ๋ชจ๋ธ์„ ๊ทธ๋ฆฌ๊ณ  ์‹ถ์„ ๋•Œ๋งˆ๋‹ค ๋ชจ๋“  ์˜ต์…˜์„ ๋‹ค์‹œ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์ „์— ๊ฐ„๋‹จํžˆ ๋ฐ”์ธ๋”ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์‹œ์ž‘ํ•˜์ž

์ด์ œ OpenGL์˜ ์‚ฌ์–‘๊ณผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, OpenGL์ด ํ›„๋“œ ์•„๋ž˜์—์„œ ์–ด๋–ป๊ฒŒ ์ž‘์šฉํ•˜๋Š”์ง€, ๊ทธ๋ฆฌ๊ณ  OpenGL์ด ์‚ฌ์šฉํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์‚ฌ์šฉ์ž ์ง€์ • ๊ธฐ์ˆ ์— ๋Œ€ํ•ด ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ฒƒ์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ–ˆ๋”๋ผ๋„ ๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

์ด ์ฑ…์—์„œ๋Š” ๊ฐ ๋‹จ๊ณ„๋ฅผ ํ†ตํ•ด OpenGL์„ ์ œ๋Œ€๋กœ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋Š” ์ถฉ๋ถ„ํ•œ ์˜ˆ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ถ”๊ฐ€ ์ž๋ฃŒ๋“ค

  • opengl.org : OpenGL์˜ ๊ณต์‹ ์›น์‚ฌ์ดํŠธ์ž…๋‹ˆ๋‹ค.
  • OpenGL registry : ๋ชจ๋“  OpenGL ๋ฒ„์ „์— ๋Œ€ํ•œ OpenGL ์‚ฌ์–‘ ๋ฐ ํ™•์žฅ์„ ํ˜ธ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค.

 

 

๋ฐ˜์‘ํ˜•
728x90

์›๋ณธ ํŽ˜์ด์ง€ - https://learnopengl.com/Introduction

 

๋‹น์‹ ์ด ์ด ํŽ˜์ด์ง€๋ฅผ ๋ฐฉ๋ฌธํ•œ ๊ฒƒ์€ ์ปดํ“จํ„ฐ ๊ทธ๋ž˜ํ”ฝ์˜ ๋‚ด์ ์ธ ์ž‘์šฉ์„ ๋ฐฐ์šฐ๊ณ  ๋ฉ‹์ง„ ์ด๋“ค์ด ํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ์„ ํ˜ผ์ž์„œ ํ•˜๊ณ  ์‹ถ์„ ๊ฒƒ์ด๋‹ค.

ํ˜ผ์ž์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์žฌ๋ฏธ์žˆ๊ณ , ์ง€๋žต์ด ํ’๋ถ€ํ•˜๋ฉฐ, ๊ทธ๋ž˜ํ”ฝ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋Œ€ํ•œ ํฐ ์ดํ•ด๋ฅผ ์ค€๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ๊ณ ๋ คํ•ด์•ผ ํ•  ๋ช‡ ๊ฐ€์ง€ ํ•ญ๋ชฉ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

์ „์ œ์กฐ๊ฑด

OpenGL์€ ์ž์ฒด ํ”Œ๋žซํผ์ด ์•„๋‹Œ ๊ทธ๋ž˜ํ”ฝ API์ด๊ธฐ ๋•Œ๋ฌธ์— ๋™์ž‘ํ•˜๊ธฐ ์œ„ํ•œ ์–ธ์–ด๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ ์„ ํƒ ์–ธ์–ด๋Š” C++์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด ์žฅ๋“ค์„ ์œ„ํ•ด์„œ๋Š” C++ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์— ๋Œ€ํ•œ ์ ์ ˆํ•œ ์ง€์‹์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ, ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๊ณ ๊ธ‰ C++ ์ฃผ์ œ๋ฅผ ํฌํ•จํ•˜์—ฌ ์‚ฌ์šฉ๋˜๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๊ฐœ๋…์„ ์„ค๋ช…ํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ C++ ์ „๋ฌธ๊ฐ€๊ฐ€ ๋  ํ•„์š”๋Š” ์—†์ง€๋งŒ "Hello World" ํ”„๋กœ๊ทธ๋žจ ์ด์ƒ์˜ ๊ฒƒ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

C++์— ๋Œ€ํ•œ ๊ฒฝํ—˜์ด ๋งŽ์ง€ ์•Š๋‹ค๋ฉด www.learncpp.com  ์—์„œ ๋ฌด๋ฃŒ ํŠœํ† ๋ฆฌ์–ผ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

 

๋˜ํ•œ, ๋„์ค‘์— ์ˆ˜ํ•™ (์„ ํ˜• ๋Œ€์ˆ˜ํ•™, ๊ธฐํ•˜ํ•™, ์‚ผ๊ฐ๋ฒ•)์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ณ  ํ•„์š”ํ•œ ์ˆ˜ํ•™์˜ ๋ชจ๋“  ํ•„์ˆ˜ ๊ฐœ๋…์„ ์„ค๋ช…ํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์ €๋Š” ์ˆ˜ํ•™์ž๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์„ค๋ช…์ด ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๋”๋ผ๋„ ๋ถˆ์™„์ „ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ์ž๋ฃŒ๋ฅผ ๋ณด๋‹ค ์™„๋ฒฝํ•˜๊ฒŒ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ์ž๋ฃŒ์— ๋Œ€ํ•œ ์ง€์นจ์„ ์ œ๊ณตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

OpenGl๋กœ์˜ ์—ฌ์ •์„ ์‹œ์ž‘ํ•˜๊ธฐ ์ „์— ํ•„์š”ํ•œ ์ˆ˜ํ•™์  ์ง€์‹์— ๋Œ€ํ•ด ๋‘๋ ค์›Œํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

๊ฑฐ์˜ ๋ชจ๋“  ๊ฐœ๋…์€ ๊ธฐ๋ณธ์ ์ธ ์ˆ˜ํ•™์  ๋ฐฐ๊ฒฝ์œผ๋กœ ํžˆ์• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€๋Šฅํ•œ ํ•œ ์ˆ˜ํ•™์„ ์ตœ์†Œํ™”ํ•˜๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋Œ€๋ถ€๋ถ„์˜ ๊ธฐ๋Šฅ์€ ์‚ฌ์šฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋Š” ํ•œ ๋ชจ๋“  ์ˆ˜ํ•™์„ ์ดํ•ดํ•  ํ•„์š”์กฐ์ฐจ ์—†์Šต๋‹ˆ๋‹ค.

 

๊ตฌ์กฐ

Learn OpenGL์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ผ๋ฐ˜์ ์ธ ์„น์…˜์œผ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

๊ฐ ์„น์…˜์—๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐœ๋…์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๋Š” ์—ฌ๋Ÿฌ ์žฅ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ ์žฅ์€ ์™ผ์ชฝ ๋ฉ”๋‰ด์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐœ๋…๋“ค์€ ์„ ํ˜•์ ์ธ ๋ฐฉ์‹์œผ๋กœ ๊ฐ€๋ฅด์ณ์ง€๋ฉฐ(๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ์ง€์‹œ๊ฐ€ ์—†๋Š” ํ•œ ์œ„์—์„œ ์•„๋ž˜๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค) ๊ฐ ์žฅ์—์„œ ๋ฐฐ๊ฒฝ ์ด๋ก ๊ณผ ์‹ค์ œ์ ์ธ ์ธก๋ฉด์„ ์„ค๋ช…ํ•œ๋‹ค.

 

๊ฐœ๋…์„ ๋” ์‰ฝ๊ฒŒ ๋”ฐ๋ฅด๊ณ  ์ถ”๊ฐ€๋œ ๊ตฌ์กฐ๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ฑ…์—๋Š” ์ƒ์ž, ์ฝ”๋“œ ๋ธ”๋ก, ์ƒ‰์ƒ ํžŒํŠธ ๋ฐ ๊ธฐ๋Šฅ ์ฐธ์กฐ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

๋ฐ•์Šค

1
์ดˆ๋ก์ƒ‰ ๋ฐ•์Šค ์ƒ์ž์—๋Š” OpenGL ๋˜๋Š” ๋‹น๋ฉดํ•œ ์ฃผ์ œ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ฐธ๊ณ  ์‚ฌํ•ญ ๋˜๋Š” ์œ ์šฉํ•œ ๊ธฐ๋Šฅ/ํžŒํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด
์žˆ์Šต๋‹ˆ๋‹ค.
cs
1
๋นจ๊ฐ„ ๋ฐ•์Šค ์ƒ์ž์—๋Š” ๊ฒฝ๊ณ  ๋˜๋Š” ๊ธฐํƒ€ ์ฃผ์˜ํ•ด์•ผ ํ•  ๊ธฐ๋Šฅ์ด ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.
cs

์ฝ”๋“œ

์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌ๋ฌธ์ด ๊ฐ•์กฐ๋œ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์–ด๋‘์šด ํšŒ์ƒ‰ ์ƒ์ž์— ์žˆ๋Š” ์ˆ˜๋งŽ์€ ์ž‘์€ ์ฝ”๋“œ ์กฐ๊ฐ์„ ์›น ์‚ฌ์ดํŠธ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค;

1
// ์ด ๋ฐ•์Šค๋Š” ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.
cs

์ด๊ฒƒ๋“ค์€ ์ฝ”๋“œ ์กฐ๊ฐ๋งŒ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ•„์š”ํ•˜๋‹ค๋ฉด ์ฃผ์–ด์ง„ ์ฃผ์ œ์— ํ•„์š”ํ•œ ์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ์ œ๊ณตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ƒ‰์ƒ ํžŒํŠธ

์ผ๋ถ€ ๋‹จ์–ด๋Š” ๋‹ค๋ฅธ ์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋˜์–ด ์ด ๋‹จ์–ด๋“ค์ด ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ๋” ๋ช…ํ™•ํ•˜๊ฒŒ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค.

  • ์ •์˜ : ๋…น์ƒ‰ ๋‹จ์–ด๋Š” ์ •์˜, ์ฆ‰ ๋” ์ž์ฃผ ๋“ค์„ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์˜ ์ค‘์š”ํ•œ ์ธก๋ฉด/์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ํ”„๋กœ๊ทธ๋žจ ๊ตฌ์กฐ : ๋นจ๊ฐ„์ƒ‰ ๋‹จ์–ด๋Š” ํ•จ์ˆ˜ ์ด๋ฆ„ ๋˜๋Š” ํด๋ž˜์Šค ์ด๋ฆ„์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ณ€์ˆ˜ :  ํŒŒ๋ž€์ƒ‰ ๋‹จ์–ด๋Š” ๋ชจ๋“  OpenGL ์ƒ์ˆ˜๋ฅผ ํฌํ•จํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

OpenGL ํ•จ์ˆ˜ ์ฐธ์กฐ

ํŠนํžˆ LearnOpenGl์˜ ๊ธฐ๋Šฅ์€ ์ฝ˜ํ…์ธ ์— ๋‚˜ํƒ€๋‚˜๋Š” ๋ชจ๋“  ๊ณณ์—์„œ OpenGL์˜ ๊ธฐ๋Šฅ์„ ๊ฒ€ํ† ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

์›น์‚ฌ์ดํŠธ์— ๋ฌธ์„œํ™”๋œ ์ฝ˜ํ…์ธ ์—์„œ ๊ธฐ๋Šฅ์„ ๋ฐœ๊ฒฌ๋  ๋•Œ๋งˆ๋‹ค, ๊ทธ ๊ธฐ๋Šฅ์€ ์•ฝ๊ฐ„ ๋ˆˆ์— ๋„๋Š” ๋ฐ‘์ค„๊ณผ ํ•จ๊ป˜ ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋งˆ์šฐ์Šค๋ฅผ ๊ธฐ๋Šฅ ์œ„์— ์˜ฌ๋ ค๋†“์œผ๋ฉด ์ž ์‹œ ํ›„ ํŒ์—… ์ฐฝ์— ๊ธฐ๋Šฅ์ด ์‹ค์ œ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์— ๋Œ€ํ•œ ๋ฉ‹์ง„ ๊ฐœ์š”๋ฅผ ํฌํ•จํ•˜์—ฌ ์ด ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ๊ด€๋ จ ์ •๋ณด๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ๋งˆ์šฐ์Šค๋ฅผ glEnable ์œ„์— ์˜ฌ๋ ค ๋†“์œผ๋ฉด ๋™์ž‘์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

์‹œ์ž‘ ์„น์…˜์œผ๋กœ ์ด๋™ํ•˜์—ฌ OpenGL ์—ฌ์ •์„ ์‹œ์ž‘ํ•˜์‹ญ์‹œ์˜ค!

๋ฐ˜์‘ํ˜•
728x90

error LNK2005 ~~~~~~~.obj์— ์ด๋ฏธ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค

๋ผ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋œฐ ์‹œ ํ—ค๋”ํŒŒ์ผ์„ #include ํ•˜๋Š” ๊ณณ์—์„œ ์ค‘๋ณต์œผ๋กœ ํ—ค๋” ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ค๋ฉด์„œ ์ถฉ๋Œ์„ ์ผ์œผ์ผฐ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.

 

๋”ฐ๋ผ์„œ ๋ณ€์ˆ˜ ์„ ์–ธ ๋ฐ ํ•จ์ˆ˜ ์„ ์–ธ์€ ํ—ค๋” ํŒŒ์ผ์— ํ•˜๋˜, ๊ตฌ์ฒด์ ์ธ ํ•จ์ˆ˜ ์ž‘์„ฑ์€ cpp ํŒŒ์ผ์—๋‹ค๊ฐ€ ํ•˜๋ฉด ํ•ด๊ฒฐ๋œ๋‹ค.

 

 

 

 

 

 

 

๋ฐ˜์‘ํ˜•
728x90

1. shared_ptr

- ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜๋ฅผ ๋™์‹œ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํฌ์ธํ„ฐ๊ฐ€ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅ

- ์ฐธ์กฐํ•˜๋Š” ๊ณผ์ •์—์„œ count๋ฅผ ํ•จ

- ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•ด์•ผํ•  ๊ฒฝ์šฐ(์—ฌ๋Ÿฌ๋ช…์ด์„œ ๊ฐ™์€ ์ •๋ณด ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ)

- ๋‹จ, ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ์Œ

 

2. unique_ptr

- ํ•œ ํฌ์ธํ„ฐ๋‹น ํ•œ ์š”์†Œ๋งŒ์„ ๊ฐ€๋ฆฌํ‚ด

- ์ผ๋ฐ˜์ ์ธ ๋Œ€์ž… ์—ฐ์‚ฐ์€ ๋ถˆ๊ฐ€๋Šฅํ•˜์ง€๋งŒ move ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ์†Œ์œ ๊ถŒ์„ ๋„˜๊ฒจ์ฃผ๋Š”๊ฒƒ์€ ๊ฐ€๋Šฅ(์†Œ์œ ๊ถŒ์„ ๋„˜๊ฒจ์ฃผ๋ฉด ์›๋ณธ ํฌ์ธ      ํ„ฐ๋Š” NULL๋กœ ์„ค์ •๋จ)

- NULL์ด ์•„๋‹Œ unique_ptr์€ ํ•ญ์ƒ ์ž์‹ ์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋ฅผ ์†Œ์œ ํ•˜๊ณ  ์†Œ๋ฉธ ์‹œ ์ž์‹ ์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์ž์›์„ ํŒŒ๊ดดํ•จ

- ํŒฉํ† ๋ฆฌ ํ•จ์ˆ˜์—์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ˜•ํƒœ๋กœ ์‚ฌ์šฉ๋จ

- ์†Œ์œ ๊ถŒ ๋…์  ์ž์› ๊ด€๋ฆฌ์— ์‚ฌ์šฉํ•˜์ž

 

3. weak_ptr

- ํ•˜๋‚˜์˜ ๋ณ€์ˆ˜๋ฅผ ๋™์‹œ์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ํฌ์ธํ„ฐ๊ฐ€ ์ฐธ์กฐ ๊ฐ€๋Šฅ

- count๋ฅผ ํ•˜์ง€ ์•Š๊ณ  ๋ณ€์ˆ˜๊ฐ€ ์‚ฌ๋ผ์ง€๋ฉด ์ž๋™์œผ๋กœ ์ฐธ์กฐํ•  ๋Œ€์ƒ์„ ์žƒ๊ฒŒ๋จ

- ๋ฉ”๋ชจ๋ฆฌํ•ด์ œ ๊ธฐ๋Šฅ์€ ์—†์Œ

 

4. auto_ptr

- C++ 11 ์ดํ›„์—๋Š” ์‚ฌ๋ผ์ง„ ํฌ์ธํ„ฐ

- ํ…œํ”Œ๋ฆฟ ๊ธฐ๋ฐ˜์˜ ํฌ์ธํ„ฐ๋ผ์„œ ์–ด๋–ค ํƒ€์ž…์˜ ํฌ์ธํ„ฐ๋“ ์ง€ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ

- new๋กœ ์ƒ์„ฑํ•œ ๋‹จ์ผ ๊ฐ์ฒด์—์„œ๋งŒ ๋ฉ”๋ชจ๋ฆฌ ํ•ด์ œ๋ฅผ ๋ณด์žฅํ•ด์„œ malloc ๋“ฑ์œผ๋กœ ํ• ๋‹นํ•  ๊ฒฝ์šฐ ํ•ด์ œ๊ฐ€ ๋˜์ง€ ์•Š์Œ

- ๋™์ผํ•œ ๋ฉ”๋ชจ๋ฆฌ ์œ„์น˜๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๊ฐ์ฒด๋ฅผ 2๊ฐœ ์ด์ƒ ์ƒ์„ฑํ•˜๋ฉด ์•ˆ๋จ(์ด๋Ÿฌํ•œ ๋ฌธ์ œ์ ์„ shared_ptr์—์„œ๋Š” ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ ํ†ตํ•ด์„œ ํ•ด๊ฒฐํ•จ)

- ๋‹จ์ ๋•Œ๋ฌธ์— unique_ptr๋กœ ๋Œ€์ฒดํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ๋จ

 

 

 

๋ฐ˜์‘ํ˜•
728x90

๋ณดํ†ต ์ดˆ๋ณด ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์ž๋“ค์ด ์œ ๋‹ˆํ‹ฐ์—์„œ C#์„ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€ ํ•œ๋ฒˆ ์„ค์ •ํ•ด๋†“์€ ์„ค์ •๋“ค์„ ๋Œ์–ด๋‹ค ์“ฐ๋ ค๊ณ  ์ ‘ํ•˜๊ฒŒ ๋˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.(๋ณธ์ธ ๊ฒฝํ—˜๋‹ด..)

์ตœ๊ทผ ๋ฉด์ ‘์—์„œ ์‹ฑ๊ธ€ํ†ค๊ณผ ์ „์—ญ๋ณ€์ˆ˜์˜ ์ฐจ์ด์ ์— ๋Œ€ํ•ด ์ œ๋Œ€๋กœ ๋Œ€๋‹ตํ•˜์ง€ ๋ชปํ•˜์˜€๊ธฐ๋•Œ๋ฌธ์— ๋ธ”๋กœ๊ทธ๋กœ ํ•œ๋ฒˆ ์ œ๋Œ€๋กœ ์ •๋ฆฌํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค์ด๋ž€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹œ์ž‘๋  ๋•Œ ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ์ตœ์ดˆ๋กœ ํ•œ๋ฒˆ๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ๊ทธ ๋ฉ”๋ชจ๋ฆฌ์— ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.

์‹ฑ๊ธ€ํ†ค๊ณผ ์ „์—ญ๋ณ€์ˆ˜๋Š” ์ตœ์ดˆ๋กœ ํ•œ๋ฒˆ๋งŒ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ๊ทธ ์ž์›์„ ๋Œ์–ด๋‹ค ์“ด๋‹ค๋Š” ์ ์—์„œ ๋น„์Šทํ•œ๋ฐ ๋‘˜์€ ์ฐจ์ด์ ์ด ์žˆ๋‹ค.

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด๊ณผ ์ „์—ญ๋ณ€์ˆ˜์˜ ์ฐจ์ด์ 

 

1. ์ƒ์„ฑ์‹œ์ 

์ „์—ญ๋ณ€์ˆ˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์‹คํ–‰๋  ๋•Œ ์ƒ์„ฑ

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์€ ํ•ด๋‹น ํ•จ์ˆ˜๊ฐ€ initialize๋˜๋ฉด์„œ ์ƒ์„ฑ

 

2. ์ž์›ํ• ๋‹น

์ „์—ญ ๋ณ€์ˆ˜๋Š” ์ž์›์˜ ์–‘์ด ์—„์ฒญ๋‚˜๊ฒŒ ํฌ๋‹ค๊ณ  ๊ฐ€์ •ํ•จ(ํŠน์ • ์‹œ์ ์—์„œ๋งŒ ์‚ฌ์šฉ๋œ๋‹ค๋ฉด ์—„์ฒญ๋‚œ ๋‚ญ๋น„)

์‹ฑํดํ†ค ํŒจํ„ด์€ ์‚ฌ์šฉํ•  ๋•Œ ์ž์›์„ ํ• ๋‹นํ•˜๊ณ  ์ž์‹ ์ด ์›ํ•  ๋•Œ ์ž์›์„ ํ•ด์ œ ๊ฐ€๋Šฅ

 

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋‹จ์ 

- ์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅ(private ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ)

- ์ƒํƒœ๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“ค๋ฉด ์•ˆ๋จ(์ƒํƒœ๊ฐ€ ๊ณต์œ ๋œ๋‹ค๋Š” ๊ฒƒ์€ ๋งค์šฐ ์œ„ํ—˜ํ•จ, ์œ ์ผํ•ด์•ผํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“ค์–ด์•ผํ•จ)

- ์‹ฑ๊ธ€ํ†ค์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ๊ณผ ์‹ฑ๊ธ€ํ†ค ํด๋ž˜์Šค ์‚ฌ์ด์— ์˜์กด์„ฑ์ด ์ƒ๊ธฐ๊ฒŒ ๋˜์„œ ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ ธ์„œ ์ˆ˜์ • ๋ฐ ๋‹จ์œ„ํ…Œ์ŠคํŠธ์˜ ์–ด๋ ค์›€์ด ์ƒ๊ธฐ๊ฒŒ ๋จ

- ์ „์—ญ ์ƒํƒœ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์€ ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์ง€์–‘๋˜์–ด์•ผ ํ•  ๋ชจ๋ธ(์œ„์™€ ๊ฐ™์ด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง€๊ธฐ ๋–„๋ฌธ)

- ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋‘๊ฐœ ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

 

 

Unity C#์—์„œ ์“ฐ๋Š” ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class manager : MonoBehaviour
{
    //instance๋ฅผ static์œผ๋กœ ์„ ์–ธ
    private static manager instance = null;
 
    //์œ ๋‹ˆํ‹ฐ์—์„œ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์‹œ์ž‘๋ ๋•Œ initialization ๋ถ€๋ถ„์—์„œ ์ œ์ผ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜
    void Awake(){
        //๋งŒ์•ฝ instance๊ฐ€ ๋น„์–ด์žˆ์„ ๋•Œ
        if(instance==null){
            instance=this;
        }
    }
 
    //๋‹ค๋ฅธ ํด๋ž˜์Šค์—์„œ ํ˜ธ์ถœํ• ์ˆ˜ ์žˆ๋„๋ก static ํ”„๋กœํผํ‹ฐ ์„ ์–ธ
    //ํ”„๋กœํผํ‹ฐ : ํ•„๋“œ(๋ฐ์ดํ„ฐ ๋ฉค๋ฒ„)์™€ ๋ฉ”์†Œ๋“œ ๊ฐ„ ๊ธฐ๋Šฅ์˜ ์ค‘๊ฐ„์ธ ํด๋ž˜์Šค ๋ฉค๋ฒ„์˜ ํŠน์ˆ˜ํ•œ ์œ ํ˜•
    public static manager Instance
    {
        get
        {
            if (null == instance)
            {
                return null;
            }
            return instance;
        }
    }
}
cs

 

๋ฐ˜์‘ํ˜•

'๊ณต๋ถ€ > Design Pattern' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

์ด๋ฒคํŠธ ํ ํŒจํ„ด (Event Queue Pattern)  (0) 2024.12.29
728x90

ํ…œํ”Œ๋ฆฟ ํ•จ์ˆ˜๋Š” ์ปดํŒŒ์ผ๋˜์ง€๋„ ํ˜ธ์ถœ๋˜์ง€๋„ ์•Š์€ ํ•จ์ˆ˜์˜ ํ‹€

์ œ๋„ค๋ฆญ ํ•จ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ  ์ปดํŒŒ์ผ ์‹œ์ ์— ๊ตฌ์ฒดํ™”์‹œํ‚ค๊ธฐ ์œ„ํ•œ ํ‹€์„ ๋งŒ๋“œ๋Š” ๊ฒƒ

๋งคํฌ๋กœ(#define)์™€ ๋‹ฌ๋ฆฌ ๋ณต์žกํ•œ ํ•จ์ˆ˜๋‚˜ ํด๋ž˜์Šค๋ฅผ ํ‘œํ˜„ํ•˜๋Š”๋ฐ ํ•œ๊ณ„๊ฐ€ ์—†๋‹ค.

์ œ๋„ค๋ฆญ ํด๋ž˜์Šค(generic class)๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 

ํ…œํ”Œ๋ฆฟ ํ•จ์ˆ˜์˜ ์žฅ์ 

- ํ•จ์ˆ˜ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜์—ฌ ์†Œํ”„ํŠธ์›จ์–ด์˜ ์ƒ์‚ฐ์„ฑ๊ณผ ์œ ์—ฐ์„ฑ์„ ๋†’์ž„

 

ํ…œํ”Œ๋ฆฟ ํ•จ์ˆ˜์˜ ๋‹จ์ 

- ์ปดํŒŒ์ผ๋Ÿฌ์— ๋”ฐ๋ผ์„œ ํ…œํ”Œ๋ฆฟ์ด ์ง€์›๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์–ด์„œ ํฌํŒ…์— ์ทจ์•ฝ

- ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๊ฐ€ ๋นˆ์•ฝํ•˜์—ฌ ๋””๋ฒ„๊น…์— ๋งŽ์€ ์–ด๋ ค์›€์ด ์žˆ์Œ

 

*swap ํ•จ์ˆ˜๋ฅผ ํ…œํ”Œ๋ฆฟ ํ•จ์ˆ˜๋กœ ํ‘œํ˜„*

1
2
3
4
5
6
7
8
template <class T>
void swap(T &a, T &b)
{
    T temp;
    temp = a;
    a=b;
    b=tmp;
}
cs

 

 

 

 

 

 

๋ฐ˜์‘ํ˜•
728x90

์•ž์„  ๊ฐœ๋…

 

Velocity Obstacle(VO)๋ž€?

๋…ผ๋ฌธ ์ฐธ๊ณ  : Motion Planning in Dynamic Environments using Velocity Obstacles - 1998๋…„๋„ ๋ฐœํ–‰ ๋…ผ๋ฌธ์˜ ํ•ต์‹ฌ ๋‚ด์šฉ- ์†๋„ ์žฅ์• ๋ฌผ์€ ๋ฐ”๋€Œ๋Š” ์‹œ๊ฐ„ ํ™˜๊ฒฝ์„ ์œ„ํ•œ configuration space obstacle์˜ ํ™•์žฅ ๊ฐœ๋…์ด๋‹ค. ์ฆ‰ ์‹ค์‹œ๊ฐ„ ํ™˜๊ฒฝ์—

dana3711.tistory.com


์ƒˆ๋กœ์šด ๊ฐœ๋…์ธ Reciprocal Velocity Obstacle(์ดํ•˜ RVO)๋ฅผ ์ œ์•ˆํ•จ
๊ฐ ์—์ด์ „ํŠธ๊ฐ€ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์™€ ๋ช…์‹œ์ ์œผ๋กœ ํ†ต์‹ ํ•˜์ง€ ์•Š๊ณ  ๋…๋ฆฝ์ ์œผ๋กœ ์›€์ง์ด๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•จ

๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์ด ์œ ์‚ฌํ•œ ์ถฉ๋Œ ํšŒํ”ผ ์ถ”๋ก ์„ ์•”๋ฌต์ ์œผ๋กœ ๊ฐ€์ •ํ•จ์œผ๋กœ์จ ๋‹ค๋ฅธ ๊ฐ์ฒด์˜ ๋ฐ˜์‘์  ํ–‰๋™์„ ๊ณ ๋ คํ•จ
์ •์  ์žฅ์• ๋ฌผ๊ณผ ์ด๋™ ์žฅ์• ๋ฌผ์„ ๋ชจ๋‘ ํฌํ•จํ•˜๋Š” ์ธ๊ตฌ ๋ฐ€๋„๊ฐ€ ๋†’์€ ํ™˜๊ฒฝ์—์„œ ์ˆ˜๋ฐฑ ๊ฐœ์˜ ์—์ด์ „ํŠธ๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์— ๊ฐœ๋…์„ ์ ์šฉํ•˜๊ณ , ๋„์ „์ ์ธ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์‹ค์‹œ๊ฐ„ ๋ฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์„ฑ๋Šฅ์„ ๋‹ฌ์„ฑํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์คŒ
์‚ฌ์šฉํ•˜๋Š” ORCA ๊ฐœ๋…์˜ ๊ฒฝ์šฐ ๋กœ๋ณดํ‹ฑ์Šค์—์„œ ๋กœ๋ด‡๊ฐ„์˜ ์ถฉ๋Œ์„ ๋ง‰๊ธฐ ์œ„ํ•ด์„œ๋„ ์“ฐ์ž„

 

์ˆ˜์ •ํ•˜๊ณ ์ž ํ•œ ๊ฒƒ

Velocity Obstacle(VO)์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ง„๋™ํ˜„์ƒ์„ ์ˆ˜์ •ํ•˜๊ณ ์ž ์ œ์ž‘ํ•จ

 

ํ•ต์‹ฌ ๋‚ด์šฉ

์›€์ง์ด๋Š” ์žฅ์• ๋ฌผ๋“ค ์‚ฌ์ด์—์„œ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ์›€์ง์ž„์„ ์œ„ํ•ด ๋„์ž…๋œ VO(Velocity Obstacle) ๊ฐœ๋…์˜ ํ™•์žฅ

ORCA(Optimal Reciprocal Collision Avoidance)๋ผ๋Š” ๊ฐœ๋…์„ ๋„์ž…ํ•˜์—ฌ ๊ฐ ๊ฐ์ฒด๊ฐ„์˜ ์†๋„๋ฅผ ๊ณ„์‚ฐํ•œ ํ›„ ๊ทธ ์ฑ…์ž„์„ ๊ฐ๊ฐ ๋ฐ˜ํ‹ˆ์”ฉ ๊ฐ€์ง€๊ฒŒ ๋งŒ๋“ค์–ด์„œ ๊ตฐ์ค‘์˜ ๋ญ‰์น˜๋Š” ํ˜„์ƒ์„ ์ค„์–ด๋“ค๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒƒ

๊ฒฐ๊ตญ ๋ณ‘๋ชฉ ํ˜„์ƒ(Bottleneck)์„ ๊ฐœ์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ œ์ž‘

 

- ๋ฏผ์ฝ”์šฐ์Šคํ‚ค ํ•ฉ (๋ฏผ์ฝ”ํ”„์Šคํ‚ค ๋ง์…ˆ)

๊ธฐํ•˜ํ•™์—์„œ, ์œ ํด๋ฆฌ๋“œ ๊ณต๊ฐ„์˜ ์œ„์น˜๋ฒกํ„ฐ A์™€ B์˜ ๋‘ ์ง‘ํ•ฉ์˜ ๋ฏผ์ฝ”์Šคํ‚ค ํ•ฉ(ํŒฝ์ฐฝ)์€ A์— ์žˆ๋Š” ๋ชจ๋“  ๋ฒกํ„ฐ๋ฅผ B์— ์žˆ๋Š” ๊ฐ๊ฐ์˜ ๋ฒกํ„ฐ์— ๋”ํ•ด์„œ ๋งŒ๋“ค์–ด์ง„๋‹ค.
 

 
 
๋ฏผ์ฝ”ํ”„์Šคํ‚ค ๋ง์…ˆ์€ ์žฅ์• ๋ฌผ ์‚ฌ์ด๋กœ ์ง€๋‚˜๋Š” ๋ชจ์…˜๊ณ„ํš์— ์‚ฌ์šฉ๋œ๋‹ค.

 

์ถ”๊ฐ€ ์ฐธ๊ณ  ์ž๋ฃŒ

 

Minkowski sum of convex polygons - Algorithms for Competitive Programming

Minkowski sum of convex polygons Definition Consider two sets $A$ and $B$ of points on a plane. Minkowski sum $A + B$ is defined as $\{a + b| a \in A, b \in B\}$. Here we will consider the case when $A$ and $B$ consist of convex polygons $P$ and $Q$ with t

cp-algorithms.com

 

๋ฏผ์ฝ”ํ”„์Šคํ‚ค ๋ง์…ˆ - ์œ„ํ‚ค๋ฐฑ๊ณผ, ์šฐ๋ฆฌ ๋ชจ๋‘์˜ ๋ฐฑ๊ณผ์‚ฌ์ „

์œ„ํ‚ค๋ฐฑ๊ณผ, ์šฐ๋ฆฌ ๋ชจ๋‘์˜ ๋ฐฑ๊ณผ์‚ฌ์ „. ๋นจ๊ฐ„ ๋„ํ˜•์€ ํŒŒ๋ž€ ๋„ํ˜•๊ณผ ์ดˆ๋ก์ƒ‰ ๋„ํ˜•์˜ ๋ฏผ์ฝ”ํ”„์Šคํ‚ค ๋ง์…ˆ์ด๋‹ค. ๊ธฐํ•˜ํ•™์—์„œ, ์œ ํด๋ฆฌ๋“œ ๊ณต๊ฐ„์˜ ์œ„์น˜๋ฒกํ„ฐ A์™€ B์˜ ๋‘ ์ง‘ํ•ฉ์˜ ๋ฏผ์ฝ”ํ”„์Šคํ‚ค ํ•ฉ(ํŒฝ์ฐฝ์ด๋ผ๊ณ ๋„ ์•Œ๋ ค์ ธ

ko.wikipedia.org

 

 

์‹ค์ œ ์ž‘๋™ RVO2 Library

๐Ÿ’กRVOSimulator-> doStep()

 

doStep์„ ์‹คํ–‰ํ•˜๋ฉด ํ•œํ”„๋ ˆ์ž„์ด ์ง„ํ–‰๋œ๋‹ค.

void RVOSimulator::doStep(float powfScalar)
{
    kdTree_->buildAgentTree();

    this->powfScalar = powfScalar;

#ifdef _OPENMP
#pragma omp parallel for
#endif
    for (int i = 0; i < static_cast<int>(agents_.size()); ++i) {
        agents_[i]->computeNeighbors();
        agents_[i]->computeNewVelocity();
        //agents_[i]->computeNewVelocityE();
    }

#ifdef _OPENMP
#pragma omp parallel for
#endif
    for (int i = 0; i < static_cast<int>(agents_.size()); ++i) {
        agents_[i]->update();
    }

    globalTime_ += timeStep_;
}

 

๋จผ์ € kdTree์— ๋Œ€ํ•œ ์ •๋ณด๋“ค์„ ๋‹ค์‹œ ์ƒ์„ฑํ•œ๋‹ค.

void KdTree::buildAgentTree()
{
	if (agents_.size() < sim_->agents_.size()) {
		for (size_t i = agents_.size(); i < sim_->agents_.size(); ++i) {
			agents_.push_back(sim_->agents_[i]);
		}

		agentTree_.resize(2 * agents_.size() - 1);
	}

	if (!agents_.empty()) {
		buildAgentTreeRecursive(0, agents_.size(), 0);
	}
}

 

ํ˜„์žฌ agent์˜ ์ˆ˜์™€ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” agent์˜ ์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ (์ฆ‰, ์ถ”๊ฐ€๋  ๋•Œ) ์ƒˆ๋กœ์šด agent๋ฅผ vector์— ์ถ”๊ฐ€ํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  Agent kd-tree๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

 

void KdTree::buildAgentTreeRecursive(size_t begin, size_t end, size_t node)
{
	agentTree_[node].begin = begin;
	agentTree_[node].end = end;
	agentTree_[node].minX = agentTree_[node].maxX = agents_[begin]->position_.x();
	agentTree_[node].minY = agentTree_[node].maxY = agents_[begin]->position_.y();

	for (size_t i = begin + 1; i < end; ++i) {
		agentTree_[node].maxX = std::max(agentTree_[node].maxX, agents_[i]->position_.x());
		agentTree_[node].minX = std::min(agentTree_[node].minX, agents_[i]->position_.x());
		agentTree_[node].maxY = std::max(agentTree_[node].maxY, agents_[i]->position_.y());
		agentTree_[node].minY = std::min(agentTree_[node].minY, agents_[i]->position_.y());
	}

	if (end - begin > MAX_LEAF_SIZE) {
		/* No leaf node. (leaf node : ๋ถ€๋ชจ๊ฐ€ ์—†๋Š” ์ตœ์ƒ์œ„ ๋…ธ๋“œ) */
		const bool isVertical = (agentTree_[node].maxX - agentTree_[node].minX > agentTree_[node].maxY - agentTree_[node].minY);
		const float splitValue = (isVertical ? 0.5f * (agentTree_[node].maxX + agentTree_[node].minX) : 0.5f * (agentTree_[node].maxY + agentTree_[node].minY));

		size_t left = begin;
		size_t right = end;

		while (left < right) {
			while (left < right && (isVertical ? agents_[left]->position_.x() : agents_[left]->position_.y()) < splitValue) {
				++left;
			}

			while (right > left && (isVertical ? agents_[right - 1]->position_.x() : agents_[right - 1]->position_.y()) >= splitValue) {
				--right;
			}

			if (left < right) {
				std::swap(agents_[left], agents_[right - 1]);
				++left;
				--right;
			}
		}

		if (left == begin) {
			++left;
			++right;
		}

		agentTree_[node].left = node + 1;
		agentTree_[node].right = node + 2 * (left - begin);

		buildAgentTreeRecursive(begin, left, agentTree_[node].left);
		buildAgentTreeRecursive(left, end, agentTree_[node].right);
	}
}

 

 

๐Ÿ’กAgent -> computeNeighbors()

void Agent::computeNeighbors()
{
	obstacleNeighbors_.clear();
	float rangeSq = sqr(timeHorizonObst_ * maxSpeed_ + radius_);
	sim_->kdTree_->computeObstacleNeighbors(this, rangeSq);

	agentNeighbors_.clear();

	if (maxNeighbors_ > 0) {
		rangeSq = sqr(neighborDist_);
		sim_->kdTree_->computeAgentNeighbors(this, rangeSq);
	}
}

 

๋จผ์ € Agent์˜ ์ด์›ƒ๋“ค(๋‚˜๋ž‘ ๊ฐ™์ด ์›€์ง์ด๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋Š” Agent๋“ค์— ๋Œ€ํ•ด ๊ณ„์‚ฐ์„ ํ•œ๋‹ค.

rangeSq๋Š” ์†๋„์™€ timeHorizonObst(์˜ต์…˜)์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง€๋„๋ก ๋งŒ๋“  sqr(๋ฃจํŠธ)๋ฅผ ์ ์šฉํ•œ ๋ฐ˜์ง€๋ฆ„์ด๋‹ค.

ํ•ด๋‹น ๋ณ€์ˆ˜๋ฅผ kdTree->computeAgentNeighbors() ํ•จ์ˆ˜๋กœ ๋„˜๊ฒจ์ค€๋‹ค.

์ด์ค‘์— RVO๋Š” Nearest Neighbor ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š”๋“ฏํ•˜๋‹ค.

computeObstacleNeighbors๋Š” ์›€์ง์ด์ง€ ์•Š๋Š” ๋ฐฉํ•ด๋ฌผ์„ ๊ณ„์‚ฐํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ๊ณ„์‚ฐํ•œ๋‹ค.

๐Ÿ’กk-d Tree
k์ฐจ์› ๊ณต๊ฐ„์˜ ์ ๋“ค์„ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๊ณต๊ฐ„ ๋ถ„ํ•  ์ž๋ฃŒ ๊ตฌ์กฐ
๋ณดํ†ต ๋‹ค์ฐจ์› ๊ณต๊ฐ„์—์„œ ํƒ์ƒ‰ํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ฒ•
Range Search, Nearest neighbor ๋“ฑ์˜ ๋ฌธ์ œ์— ์ ์šฉ
๐Ÿ’กkNN
์ฃผ์–ด์ง„ Point์™€ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด(์ฃผ์–ด์ง„ set์•ˆ์˜) ์ ์„ ์ฐพ๋Š” ๊ฒƒ

1. k ์ด์›ƒ์˜ ๊ธฐ์ค€์„ ์ •์˜
2. test ์…‹์˜ ๊ฐœ๋ณ„ ํฌ์ธํŠธ์— ๋Œ€ํ•ด์„œ k ๊ฐœ์˜ ์ด์›ƒ์„ ์ฐพ์Œ
3. ์ด์›ƒ์˜ output์„ ๊ฐ€์ง€๊ณ  ์˜ˆ์ธก๊ฐ’์„ ์ƒ์„ฑ

 

void KdTree::computeAgentNeighbors(Agent *agent, float &rangeSq) const
{
    queryAgentTreeRecursive(agent, rangeSq, 0);
}

 

kd-tree ๋‚ด์—์„œ ์œ„์น˜๋ฅผ ์ฐพ์•„์„œ insertํ•ด์ค€๋‹ค.

์ฐพ์€ agentTree๊ฐ€ 10๊ฐœ ์ดํ•˜๋ฉด ๊ทธ๋Œ€๋กœ ์‚ฝ์ž…ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด kd-tree ๋‚ด์—์„œ ์œ„์น˜๋ฅผ ๋‹ค์‹œ ์ •ํ™•ํ•˜๊ฒŒ ํƒ์ƒ‰ํ•œ๋‹ค.

kNN์—์„œ ์ฃผ์–ด์ง„ set์ด 10๊ฐœ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

void KdTree::queryAgentTreeRecursive(Agent *agent, float &rangeSq, size_t node) const
{
	//agentTree์˜ ํฌ๊ธฐ๊ฐ€ 10๋ณด๋‹ค ์ž‘๋‹ค๋ฉด agent์˜ ์ด์›ƒ์— ํ•ด๋‹น agent๋ฅผ insert
	if (agentTree_[node].end - agentTree_[node].begin <= MAX_LEAF_SIZE) {
		for (size_t i = agentTree_[node].begin; i < agentTree_[node].end; ++i) {
			agent->insertAgentNeighbor(agents_[i], rangeSq);
		}
	}
	else {
		const float distSqLeft = sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minX - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].left].maxX)) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minY - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].left].maxY));

		const float distSqRight = sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minX - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].right].maxX)) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minY - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].right].maxY));

		if (distSqLeft < distSqRight) {
			if (distSqLeft < rangeSq) {
				queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);

				if (distSqRight < rangeSq) {
					queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
				}
			}
		}
		else {
			if (distSqRight < rangeSq) {
				queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);

				if (distSqLeft < rangeSq) {
					queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
				}
			}
		}

	}
}

 

๐Ÿ’กAgent -> computeNewVelocity()

 

์ฃผ๋ณ€ ์ด์›ƒ์„ ๊ฒฐ์ •ํ•˜์˜€์œผ๋ฉด ์ƒˆ๋กœ์šด ์†๋„๋ฅผ ํƒ์ƒ‰ํ•œ๋‹ค.

์ƒˆ๋กœ์šด ์†๋„๋ฅผ ์œ„ํ•ด ORCA ๋ผ์ธ์„ ์ƒˆ๋กญ๊ฒŒ ๋งŒ๋“ ๋‹ค.

ํ–‰๋ ฌ์‹์˜ ์ ˆ๋Œ€๊ฐ’์€ ๋„ํ˜•์˜ ๋ฉด์ ์„ ์˜๋ฏธํ•œ๋‹ค.

 

		const Obstacle *obstacle1 = obstacleNeighbors_[i].second;
		const Obstacle *obstacle2 = obstacle1->nextObstacle_;

		const Vector2 relativePosition1 = obstacle1->point_ - position_;
		const Vector2 relativePosition2 = obstacle2->point_ - position_;

		/*
		 * Check if velocity obstacle of obstacle is already taken care of by
		 * previously constructed obstacle ORCA lines.
		 * ์žฅ์• ๋ฌผ์˜ ์†๋„ ์žฅ์• ๋ฌผ์ด ์ด์ „์— ๊ตฌ์ถ•๋œ ์žฅ์• ๋ฌผ ORCA ๋ผ์ธ์— ์˜ํ•ด 
		 * ์ด๋ฏธ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
		 */
		bool alreadyCovered = false;

		for (size_t j = 0; j < orcaLines_.size(); ++j) {
			//det : ํ–‰๋ ฌ์‹, radius_ : agent์˜ ๋ฐ˜์ง€๋ฆ„
			if (det(invTimeHorizonObst * relativePosition1 - orcaLines_[j].point, orcaLines_[j].direction) - invTimeHorizonObst * radius_ >= -RVO_EPSILON 
			&& det(invTimeHorizonObst * relativePosition2 - orcaLines_[j].point, orcaLines_[j].direction) - invTimeHorizonObst * radius_ >=  -RVO_EPSILON) {
				alreadyCovered = true;
				break;
			}
		}

		if (alreadyCovered) {
			continue;
		}

 

๋จผ์ € ๊ตฌ์ถ•๋œ ์žฅ์• ๋ฌผ ORCA ๋ผ์ธ์— ์˜ํ•ด ์ด๋ฏธ ์ฒ˜๋ฆฌ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ์ฒ˜๋ฆฌ ๋˜์—ˆ๋‹ค๋ฉด ์ƒ๋žตํ•œ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ์žฅ์• ๋ฌผ ORCA ๋ผ์ธ์„ ๋งŒ๋“ ๋‹ค.

	/* Create obstacle ORCA lines. */
	for (size_t i = 0; i < obstacleNeighbors_.size(); ++i) {
	
		/* Not yet covered. Check for collisions. */

		const float distSq1 = absSq(relativePosition1);
		const float distSq2 = absSq(relativePosition2);

		const float radiusSq = sqr(radius_);

		const Vector2 obstacleVector = obstacle2->point_ - obstacle1->point_;
		const float s = (-relativePosition1 * obstacleVector) / absSq(obstacleVector);
		const float distSqLine = absSq(-relativePosition1 - s * obstacleVector);

		Line line;

		if (s < 0.0f && distSq1 <= radiusSq) {
			/* Collision with left vertex. Ignore if non-convex. */
			if (obstacle1->isConvex_) {
				line.point = Vector2(0.0f, 0.0f);
				line.direction = normalize(Vector2(-relativePosition1.y(), relativePosition1.x()));
				orcaLines_.push_back(line);
			}

			continue;
		}
		else if (s > 1.0f && distSq2 <= radiusSq) {
			/* Collision with right vertex. Ignore if non-convex
			 * or if it will be taken care of by neighoring obstace */
			if (obstacle2->isConvex_ && det(relativePosition2, obstacle2->unitDir_) >= 0.0f) {
				line.point = Vector2(0.0f, 0.0f);
				line.direction = normalize(Vector2(-relativePosition2.y(), relativePosition2.x()));
				orcaLines_.push_back(line);
			}

			continue;
		}
		else if (s >= 0.0f && s < 1.0f && distSqLine <= radiusSq) {
			/* Collision with obstacle segment. */
			line.point = Vector2(0.0f, 0.0f);
			line.direction = -obstacle1->unitDir_;
			orcaLines_.push_back(line);
			continue;
		}

		//์•„๋ž˜ ์ฝ”๋“œ๋“ค ์‹คํ–‰
        //...

 

		/*
		 * No collision.
		 * Compute legs. When obliquely viewed, both legs can come from a single
		 * vertex. Legs extend cut-off line when nonconvex vertex.
		 * ์ถฉ๋Œ์€ ์—†์Šต๋‹ˆ๋‹ค.
		 * leg๋ฅผ ๊ณ„์‚ฐํ•˜์„ธ์š”. ๋น„์Šค๋“ฌํžˆ ๋ณผ ๋•Œ, ๋‘ leg๋Š” ํ•˜๋‚˜์˜ ๊ผญ์ง“์ ์—์„œ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 
		 * leg๋Š” ๋ณผ๋กํ•˜์ง€ ์•Š์€ ๊ผญ์ง“์ ์—์„œ ์ ˆ๋‹จ์„ ์„ ์—ฐ์žฅํ•ฉ๋‹ˆ๋‹ค.
		 */

		Vector2 leftLegDirection, rightLegDirection;

		if (s < 0.0f && distSqLine <= radiusSq) {
			/*
			 * Obstacle viewed obliquely so that left vertex 
			 * defines velocity obstacle.
			 * ์™ผ์ชฝ ๊ผญ์ง“์ ์ด ์†๋„ ์žฅ์• ๋ฌผ์„ ์ •์˜ํ•˜๋„๋ก ๋น„์Šค๋“ฌํžˆ ๋ณด์ด๋Š” ์žฅ์• ๋ฌผ.
			 */
			if (!obstacle1->isConvex_) {
				/* Ignore obstacle. */
				continue;
			}

			obstacle2 = obstacle1;

			const float leg1 = std::sqrt(distSq1 - radiusSq);
			leftLegDirection = Vector2(relativePosition1.x() * leg1 - relativePosition1.y() * radius_, relativePosition1.x() * radius_ + relativePosition1.y() * leg1) / distSq1;
			rightLegDirection = Vector2(relativePosition1.x() * leg1 + relativePosition1.y() * radius_, -relativePosition1.x() * radius_ + relativePosition1.y() * leg1) / distSq1;
		}
		else if (s > 1.0f && distSqLine <= radiusSq) {
			/*
			 * Obstacle viewed obliquely so that
			 * right vertex defines velocity obstacle.
			 * ์˜ค๋ฅธ์ชฝ ๊ผญ์ง“์ ์ด ์†๋„ ์žฅ์• ๋ฌผ์„ ์ •์˜ํ•˜๋„๋ก ๋น„์Šค๋“ฌํžˆ ๋ณด์ด๋Š” ์žฅ์• ๋ฌผ.
			 */
			if (!obstacle2->isConvex_) {
				/* Ignore obstacle. */
				continue;
			}

			obstacle1 = obstacle2;

			const float leg2 = std::sqrt(distSq2 - radiusSq);
			leftLegDirection = Vector2(relativePosition2.x() * leg2 - relativePosition2.y() * radius_, relativePosition2.x() * radius_ + relativePosition2.y() * leg2) / distSq2;
			rightLegDirection = Vector2(relativePosition2.x() * leg2 + relativePosition2.y() * radius_, -relativePosition2.x() * radius_ + relativePosition2.y() * leg2) / distSq2;
		}
		else {
			/* Usual situation. */
			if (obstacle1->isConvex_) {
				const float leg1 = std::sqrt(distSq1 - radiusSq);
				leftLegDirection = Vector2(relativePosition1.x() * leg1 - relativePosition1.y() * radius_, relativePosition1.x() * radius_ + relativePosition1.y() * leg1) / distSq1;
			}
			else {
				/* Left vertex non-convex; left leg extends cut-off line. */
				leftLegDirection = -obstacle1->unitDir_;
			}

			if (obstacle2->isConvex_) {
				const float leg2 = std::sqrt(distSq2 - radiusSq);
				rightLegDirection = Vector2(relativePosition2.x() * leg2 + relativePosition2.y() * radius_, -relativePosition2.x() * radius_ + relativePosition2.y() * leg2) / distSq2;
			}
			else {
				/* Right vertex non-convex; right leg extends cut-off line. */
				rightLegDirection = obstacle1->unitDir_;
			}
		}
/*
		 * Legs can never point into neighboring edge when convex vertex,
		 * take cutoff-line of neighboring edge instead. If velocity projected on
		 * "foreign" leg, no constraint is added.
		 */

		const Obstacle *const leftNeighbor = obstacle1->prevObstacle_;

		bool isLeftLegForeign = false;
		bool isRightLegForeign = false;

		if (obstacle1->isConvex_ && det(leftLegDirection, -leftNeighbor->unitDir_) >= 0.0f) {
			/* Left leg points into obstacle. */
			leftLegDirection = -leftNeighbor->unitDir_;
			isLeftLegForeign = true;
		}

		if (obstacle2->isConvex_ && det(rightLegDirection, obstacle2->unitDir_) <= 0.0f) {
			/* Right leg points into obstacle. */
			rightLegDirection = obstacle2->unitDir_;
			isRightLegForeign = true;
		}

		/* Compute cut-off centers. */
		const Vector2 leftCutoff = invTimeHorizonObst * (obstacle1->point_ - position_);
		const Vector2 rightCutoff = invTimeHorizonObst * (obstacle2->point_ - position_);
		const Vector2 cutoffVec = rightCutoff - leftCutoff;

		/* Project current velocity on velocity obstacle. */

		/* Check if current velocity is projected on cutoff circles. */
		const float t = (obstacle1 == obstacle2 ? 0.5f : ((velocity_ - leftCutoff) * cutoffVec) / absSq(cutoffVec));
		const float tLeft = ((velocity_ - leftCutoff) * leftLegDirection);
		const float tRight = ((velocity_ - rightCutoff) * rightLegDirection);

		if ((t < 0.0f && tLeft < 0.0f) || (obstacle1 == obstacle2 && tLeft < 0.0f && tRight < 0.0f)) {
			/* Project on left cut-off circle. */
			const Vector2 unitW = normalize(velocity_ - leftCutoff);

			line.direction = Vector2(unitW.y(), -unitW.x());
			line.point = leftCutoff + radius_ * invTimeHorizonObst * unitW;
			orcaLines_.push_back(line);
			continue;
		}
		else if (t > 1.0f && tRight < 0.0f) {
			/* Project on right cut-off circle. */
			const Vector2 unitW = normalize(velocity_ - rightCutoff);

			line.direction = Vector2(unitW.y(), -unitW.x());
			line.point = rightCutoff + radius_ * invTimeHorizonObst * unitW;
			orcaLines_.push_back(line);
			continue;
		}
/*
		 * Project on left leg, right leg, or cut-off line, whichever is closest
		 * to velocity.
		 */
		const float distSqCutoff = ((t < 0.0f || t > 1.0f || obstacle1 == obstacle2) ? std::numeric_limits<float>::infinity() : absSq(velocity_ - (leftCutoff + t * cutoffVec)));
		const float distSqLeft = ((tLeft < 0.0f) ? std::numeric_limits<float>::infinity() : absSq(velocity_ - (leftCutoff + tLeft * leftLegDirection)));
		const float distSqRight = ((tRight < 0.0f) ? std::numeric_limits<float>::infinity() : absSq(velocity_ - (rightCutoff + tRight * rightLegDirection)));

		if (distSqCutoff <= distSqLeft && distSqCutoff <= distSqRight) {
			/* Project on cut-off line. */
			line.direction = -obstacle1->unitDir_;
			line.point = leftCutoff + radius_ * invTimeHorizonObst * Vector2(-line.direction.y(), line.direction.x());
			orcaLines_.push_back(line);
			continue;
		}
		else if (distSqLeft <= distSqRight) {
			/* Project on left leg. */
			if (isLeftLegForeign) {
				continue;
			}

			line.direction = leftLegDirection;
			line.point = leftCutoff + radius_ * invTimeHorizonObst * Vector2(-line.direction.y(), line.direction.x());
			orcaLines_.push_back(line);
			continue;
		}
		else {
			/* Project on right leg. */
			if (isRightLegForeign) {
				continue;
			}

			line.direction = -rightLegDirection;
			line.point = rightCutoff + radius_ * invTimeHorizonObst * Vector2(-line.direction.y(), line.direction.x());
			orcaLines_.push_back(line);
			continue;
		}

 

	const size_t numObstLines = orcaLines_.size();

	const float invTimeHorizon = 1.0f / timeHorizon_;

	/* Create agent ORCA lines. */
	for (size_t i = 0; i < agentNeighbors_.size(); ++i) {
		const Agent *const other = agentNeighbors_[i].second;

		const Vector2 relativePosition = other->position_ - position_;
		const Vector2 relativeVelocity = velocity_ - other->velocity_;
		const float distSq = absSq(relativePosition);
		const float combinedRadius = radius_ + other->radius_;
		const float combinedRadiusSq = sqr(combinedRadius);

		Line line;
		Vector2 u;

		if (distSq > combinedRadiusSq) {
			/* No collision. */
			const Vector2 w = relativeVelocity - invTimeHorizon * relativePosition;
			/* Vector from cutoff center to relative velocity. */
			const float wLengthSq = absSq(w);

			const float dotProduct1 = w * relativePosition;

			if (dotProduct1 < 0.0f && sqr(dotProduct1) > combinedRadiusSq * wLengthSq) {
				/* Project on cut-off circle. */
				const float wLength = std::sqrt(wLengthSq);
				const Vector2 unitW = w / wLength;

				line.direction = Vector2(unitW.y(), -unitW.x());
				u = (combinedRadius * invTimeHorizon - wLength) * unitW;
			}
			else {
				/* Project on legs. */
				const float leg = std::sqrt(distSq - combinedRadiusSq);

				if (det(relativePosition, w) > 0.0f) {
					/* Project on left leg. */
					line.direction = Vector2(relativePosition.x() * leg - relativePosition.y() * combinedRadius, relativePosition.x() * combinedRadius + relativePosition.y() * leg) / distSq;
				}
				else {
					/* Project on right leg. */
					line.direction = -Vector2(relativePosition.x() * leg + relativePosition.y() * combinedRadius, -relativePosition.x() * combinedRadius + relativePosition.y() * leg) / distSq;
				}

				const float dotProduct2 = relativeVelocity * line.direction;

				u = dotProduct2 * line.direction - relativeVelocity;
			}
		}
		else {
			/* Collision. Project on cut-off circle of time timeStep. */
			const float invTimeStep = 1.0f / sim_->timeStep_;

			/* Vector from cutoff center to relative velocity. */
			const Vector2 w = relativeVelocity - invTimeStep * relativePosition;

			const float wLength = abs(w);
			const Vector2 unitW = w / wLength;

			line.direction = Vector2(unitW.y(), -unitW.x());
			u = (combinedRadius * invTimeStep - wLength) * unitW;
		}

		line.point = velocity_ + 0.5f * u;
		orcaLines_.push_back(line);
	}

	size_t lineFail = linearProgram2(orcaLines_, maxSpeed_, prefVelocity_, false, newVelocity_);

	if (lineFail < orcaLines_.size()) {
		linearProgram3(orcaLines_, numObstLines, lineFail, maxSpeed_, newVelocity_);
	}

 

๊ณ„์‚ฐ๋œ ORCA ๋ผ์ธ๋“ค๊ณผ Linear Programming์„ ์ด์šฉํ•ด์„œ ์ƒˆ๋กœ์šด ์†๋„๋ฅผ ์–ป๋Š”๋‹ค.

๐Ÿ’กLinear Programming
๋‹ค์–‘ํ•œ ์ œ์•ฝ ์กฐ๊ฑด์„ ๊ณ ๋ คํ•˜๋ฉด์„œ ์„ ํ˜• ํ•จ์ˆ˜๋ฅผ ์ตœ๋Œ€ํ™”ํ•˜๊ฑฐ๋‚˜ ์ตœ์†Œํ™”ํ•˜๋Š” ์ˆ˜ํ•™์  ๋ชจ๋ธ๋ง ๊ธฐ์ˆ 
size_t lineFail = linearProgram2(orcaLines_, maxSpeed_, prefVelocity_, false, newVelocity_);

if (lineFail < orcaLines_.size()) {
	linearProgram3(orcaLines_, numObstLines, lineFail, maxSpeed_, newVelocity_);
}

 

result == newVelocity_๋ž‘ ๊ฐ™๋‹ค.

size_t linearProgram2(const std::vector<Line> &lines, float radius, const Vector2 &optVelocity, bool directionOpt, Vector2 &result)
{
	if (directionOpt) {
		//์ตœ์ ํ™”๋˜์–ด ์žˆ๋Š” ๋ฐฉํ–ฅ. ์ด ๊ฒฝ์šฐ ์ตœ์ ํ™” ์†๋„๋Š” ๋‹จ์œ„ ๊ธธ์ด์ž…๋‹ˆ๋‹ค.
		result = optVelocity * radius;
	}
	else if (absSq(optVelocity) > sqr(radius)) {
		/* ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ ๊ณผ ๋ฐ”๊นฅ์ชฝ ์›์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค. */
		result = normalize(optVelocity) * radius;
	}
	else {
		/* ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ ๊ณผ ์•ˆ์ชฝ ์›์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค. */
		result = optVelocity;
	}

	for (size_t i = 0; i < lines.size(); ++i) {
		//๋‘ ์„ ์ด ๊ฐ™์œผ๋ฉด 0์„ ์ถœ๋ ฅ
		if (det(lines[i].direction, lines[i].point - result) > 0.0f) { // ํ‰ํ–‰์‚ฌ๋ณ€ํ˜•์˜ ๋ฉด์ 
			/* ๊ฒฐ๊ณผ๊ฐ€ ์ œ์•ฝ์กฐ๊ฑด i๋ฅผ ๋งŒ์กฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์ตœ์ ์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. */
			const Vector2 tempResult = result;

			if (!linearProgram1(lines, i, radius, optVelocity, directionOpt, result)) {
				result = tempResult;
				return i;
			}
		}
	}

	return lines.size();
}

 

 

bool linearProgram1(const std::vector<Line> &lines, size_t lineNo, float radius, const Vector2 &optVelocity, bool directionOpt, Vector2 &result)
{
	//์Šค์นผ๋ผ ๊ณฑ, ๋ฒกํ„ฐ์˜ ๋‚ด์ 
	const float dotProduct = lines[lineNo].point * lines[lineNo].direction;
	const float discriminant = sqr(dotProduct) + sqr(radius) - absSq(lines[lineNo].point);

	if (discriminant < 0.0f) {
		/* ์ตœ๋Œ€ ์†๋„ ์›์€ line lineNo๋ฅผ ์™„์ „ํžˆ ๋ฌดํšจํ™”ํ•ฉ๋‹ˆ๋‹ค. */
		return false;
	}

	const float sqrtDiscriminant = std::sqrt(discriminant);
	float tLeft = -dotProduct - sqrtDiscriminant;
	float tRight = -dotProduct + sqrtDiscriminant;

	for (size_t i = 0; i < lineNo; ++i) {
		//๋ถ„๋ชจ
		const float denominator = det(lines[lineNo].direction, lines[i].direction);
		//๋ถ„์ž
		const float numerator = det(lines[i].direction, lines[lineNo].point - lines[i].point);
		//fabs() : ์ ˆ๋Œ€๊ฐ’ ์—ฐ์‚ฐ
		if (std::fabs(denominator) <= RVO_EPSILON) {
			/* Lines lineNo๊ณผ i๋Š” (๊ฑฐ์˜) ๋‚˜๋ž€ํ•˜๋‹ค. */
			if (numerator < 0.0f) {
				return false;
			}
			else {
				continue;
			}
		}

		const float t = numerator / denominator;

		if (denominator >= 0.0f) {
			/* Line i bounds line lineNo on the right. */
			tRight = std::min(tRight, t);
		}
		else {
			/* Line i bounds line lineNo on the left. */
			tLeft = std::max(tLeft, t);
		}

		if (tLeft > tRight) {
			return false;
		}
	}

	if (directionOpt) {
		/* ์ตœ์ ํ™” ๋ฐฉํ–ฅ */
		if (optVelocity * lines[lineNo].direction > 0.0f) {
			/* ์˜ค๋ฅธ์ชฝ์œผ๋กœ ๊ทน๋‹จ์ ์œผ๋กœ. */
			result = lines[lineNo].point + tRight * lines[lineNo].direction;
		}
		else {
			/* ์™ผ์ชฝ์œผ๋กœ ๊ทน๋‹จ์ ์œผ๋กœ. */
			result = lines[lineNo].point + tLeft * lines[lineNo].direction;
		}
	}
	else {
		/* ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ์ง€์ ์„ ์ตœ์ ํ™”ํ•ฉ๋‹ˆ๋‹ค. */
		const float t = lines[lineNo].direction * (optVelocity - lines[lineNo].point);

		if (t < tLeft) {
			result = lines[lineNo].point + tLeft * lines[lineNo].direction;
		}
		else if (t > tRight) {
			result = lines[lineNo].point + tRight * lines[lineNo].direction;
		}
		else {
			result = lines[lineNo].point + t * lines[lineNo].direction;
		}
	}

	return true;
}

 

void linearProgram3(const std::vector<Line> &lines, size_t numObstLines, size_t beginLine, float radius, Vector2 &result)
{
	float distance = 0.0f;

	for (size_t i = beginLine; i < lines.size(); ++i) {
		if (det(lines[i].direction, lines[i].point - result) > distance) {
			/* ๊ฒฐ๊ณผ๊ฐ€ ์„  i์˜ ์ œ์•ฝ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. */
			std::vector<Line> projLines(lines.begin(), lines.begin() + static_cast<ptrdiff_t>(numObstLines));

			for (size_t j = numObstLines; j < i; ++j) {
				Line line;

				float determinant = det(lines[i].direction, lines[j].direction);

				if (std::fabs(determinant) <= RVO_EPSILON) {
					/* Line i ๊ณผ line j ๋Š” ๋‚˜๋ž€ํ•˜๋‹ค */
					if (lines[i].direction * lines[j].direction > 0.0f) {
						/* Line i ๊ณผ line j ๋Š” ๊ฐ™์€ ๋ฐฉํ–ฅ์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค */
						continue;
					}
					else {
						/* Line i ๊ณผ line j ๋Š” ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค */
						line.point = 0.5f * (lines[i].point + lines[j].point);
					}
				}
				else {
					line.point = lines[i].point + (det(lines[j].direction, lines[i].point - lines[j].point) / determinant) * lines[i].direction;
				}

				line.direction = normalize(lines[j].direction - lines[i].direction);
				projLines.push_back(line);
			}

			const Vector2 tempResult = result;

			if (linearProgram2(projLines, radius, Vector2(-lines[i].direction.y(), lines[i].direction.x()), true, result) < projLines.size()) {
				/* ์›์น™์ ์œผ๋กœ ์ด๋Ÿฐ ์ผ์€ ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
				 * ๊ทธ ๊ฒฐ๊ณผ๋Š” ์ •์˜์ƒ ์ด ์„ ํ˜• ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰ ๊ฐ€๋Šฅ ์˜์—ญ์— ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.
				 * ์‹คํŒจํ•  ๊ฒฝ์šฐ ์ž‘์€ ๋ถ€๋™ ์†Œ์ˆ˜์  ์˜ค์ฐจ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋ฉฐ ํ˜„์žฌ ๊ฒฐ๊ณผ๋Š” ๊ทธ๋Œ€๋กœ 
				 * ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
				 */
				result = tempResult;
			}

			distance = det(lines[i].direction, lines[i].point - result);
		}
	}
}

 

์—ฐ๊ด€ ํ‚ค์›Œ๋“œ

half plane, ORCA, Linear Programming, Velocity Obstacle, ๋ฏผ์ฝ”์šฐ์Šคํ‚ค ํ•ฉ

 

RVO ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•œ ๊ตฐ์ค‘ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ์˜ˆ์ œ ๋ชจ์Šต

 

* ์žฅ์• ๋ฌผ์—์„œ ๊ฑธ๋ฆฌ๋Š” ํ˜„์ƒ์ด ๋งŽ์ด ๋‚˜์˜ค๋Š” ์ด์œ ๋Š” RVO ์ž์ฒด๊ฐ€ ์›€์ง์ด๋Š” Obstacle๋“ค์ด ์„œ๋กœ ์ฑ…์ž„์„ ๋ฐ˜ํ‹ˆ์”ฉ ๋‚˜๋ˆ„์–ด ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ์ • ์žฅ์• ๋ฌผ์—์„œ๋Š” ํšจ๊ณผ๊ฐ€ ๋œ ๋‚˜๋Š” ๊ฒƒ์œผ๋กœ ์ถ”์ธก*

 

 

์ฐธ๊ณ  ์‚ฌ์ดํŠธ

 

[Algorithm] Linear Programming (1)

์ด ๊ธ€์€ ํฌ์Šคํ… ์˜ค์€์ง„ ๊ต์ˆ˜๋‹˜์˜ CSED331 ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ˆ˜์—…์˜ ๊ฐ•์˜ ๋‚ด์šฉ๊ณผ ์ž๋ฃŒ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

rntlqvnf.github.io

 

Optimal Reciprocal Collision Avoidance (ORCA)

We present a formal approach to reciprocal collision avoidance, where multiple independent mobile robots or agents need to avoid collisions with each other without communication among agents while moving in a common workspace. Our formulation, optimal reci

gamma.cs.unc.edu

 

Collision Avoidance

Description   Collision avoidance is a fundamental problem in many areas such as robotics and animation. To that end, we developed new techniques focused on providing fast and robust collision avoidance for multiple agents moving around obstacles and each

gamma.cs.unc.edu

 

Reciprocal Velocity Obstacles for Real-Time Multi-Agent Navigation

ABSTRACT We propose a new concept --- the "Reciprocal Velocity Obstacle" --- for real-time multi-agent navigation. We consider the case in which each agent navigates independently without explicit communication with other agents. Our formulation is an exte

gamma.cs.unc.edu

 

๋ฐ˜์‘ํ˜•

'๊ณต๋ถ€ > Crowd Simulation' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Velocity Obstacle(VO)๋ž€?  (0) 2020.01.17
728x90

 

๋…ผ๋ฌธ์˜ ํ•ต์‹ฌ ๋‚ด์šฉ

 

์†๋„ ์žฅ์• ๋ฌผ์€ ๋ฐ”๋€Œ๋Š” ์‹œ๊ฐ„ ํ™˜๊ฒฝ์„ ์œ„ํ•œ configuration space obstacle์˜ ํ™•์žฅ ๊ฐœ๋…์ด๋‹ค.

์ฆ‰ ์‹ค์‹œ๊ฐ„ ํ™˜๊ฒฝ์— ์ ํ•ฉํ•˜๋‹ค.

Velocity Obstacle(์†๋„ ์žฅ์• ๋ฌผ)์€ ๊ฐ์ฒด์˜ Velocity๊ฐ€ ์†๋„ ์žฅ์• ๋ฌผ์ธ VO ์˜์—ญ์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์œผ๋ฉด ๋ฌผ์ฒด๋Š” ์ถฉ๋Œํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฐœ๋…์ด๋‹ค.
 

๋งŒ์•ฝ ์œ„ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด A์™€ B ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•œ๋‹ค๋ฉด, A์™€ B๊ฐ€ ์ถฉ๋Œํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ A๋Š” B๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฐ„์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์œผ๋ฉด ํ”ผํ• ์ˆ˜ ์žˆ๋‹ค๋Š” ์ƒ๊ฐ์„ ๊ฐ€์ง€๋Š” ์†๋„ ์กฐ์ ˆ ๋ฐฉ๋ฒ•์ด๋‹ค.
 

 
๊ตฐ์ค‘์—์„œ ํ•œ๊ฐœ์˜ ๊ฐ์ฒด๋“ค์€ ๊ฐ๊ฐ์˜ Velocity(๋ฐฉํ–ฅ์„ ๊ฐ€์ง„ ์†๋„)๋ฅผ ๊ฐ€์ง„๋‹ค.  ์œ„์˜ ๊ทธ๋ฆผ์—์„œ๋Š” A๊ฐ€ ๊ฐ€์ง„ ์†๋„๋Š” VA๋กœ ๋‚˜ํƒ€๋‚ด๊ณ , B๊ฐ€ ๊ฐ€์ง„ ์†๋„๋Š” VB๋กœ ๋‚˜ํƒ€๋‚ด์—ˆ๋‹ค.

VO๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Configurations Space๋กœ ๋ณ€ํ™˜ํ•ด์•ผํ•˜๋Š”๋ฐ, Configuration Space๋Š” ์ˆ˜ํ•™์—์„œ๋Š” ์œ„์ƒ ๊ณต๊ฐ„์˜ ์œ„์น˜์— ๋Œ€ํ•œ ์  ๋ชจ์Œ ํ• ๋‹น์„ ์„ค๋ช…ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
์œ„์ƒ๊ณต๊ฐ„์€ ํŠน์ •ํ•œ ๊ณ„๊ฐ€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ์ƒํƒœ๋“ค์˜ ๊ณต๊ฐ„์ด๋‹ค.

์  A์˜ ์œ„์น˜์—์„œ ๋ฐ”๋ผ๋ณผ ๋•Œ A์˜ ๋ชธ์ฒด(์›ํ˜•)๊ณผ B์˜ ๋ชธ์ฒด(์›ํ˜•)์ด ๋‹ฟ์ง€ ์•Š๋Š” ์ ๊นŒ์ง€ ๊ณ ๋ คํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— A์™€B์˜ ๋ชธ์ฒด์˜ ์œ„์น˜๋“ค์„ ๊ณ ๋ คํ•œ A+B ๋ชธ์ฒด(์›ํ˜•)๊ณผ ๋งž๋‹ฟ์•„ ์žˆ๋Š” 2๊ฐœ์˜ ์ง์„ ์„ ๊ทธ์–ด์„œ VO๋ฅผ ์ •์˜ํ•œ๋‹ค.
A์—์„œ B์— ๋Œ€ํ•œ VO๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ, ์œ„์˜ ๊ทธ๋ฆผ๊ณผ ๊ฐ™์ด ์  A์˜ ์œ„์น˜์—์„œ B์˜ ์™ธ๊ณฝ์„ ์ง€๋‚˜๋Š” ์ง์„  2๊ฐœ๋ฅผ ๊ตฌํ•œ๋‹ค. ์ด ์ง์„  ๋‘๊ฐœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ VO๋Š” ํšŒ์ƒ‰ ๊ณต๊ฐ„์œผ๋กœ ํ‘œ์‹œ๋œ ๊ณต๊ฐ„์ด๋‹ค. ํ˜„์žฌ ํ”„๋ ˆ์ž„์—์„œ ์ด ๊ณต๊ฐ„์— ๋“ค์–ด๊ฐ€์ง€ ์•Š์œผ๋ฉด B์™€ ์ ˆ๋Œ€ ์ถฉ๋Œํ•˜์ง€ ์•Š๋Š”๋‹ค.
๊ตฐ์ค‘ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ Path Planning(๊ฒฝ๋กœ ๊ณ„ํš)์„ ์ง€์ •ํ•  ๋•Œ, ์ด๋Ÿฌํ•œ ์†๋„ ์žฅ์• ๋ฌผ์„ ์‘์šฉํ•ด์„œ ๋„ฃ๋Š”๋‹ค.

๋‹ค์Œ ํ”„๋ ˆ์ž„์—์„œ A๊ฐ€ B์— ๋Œ€ํ•ด ๊ณ„์‚ฐํ•œ ํšŒ์ƒ‰ ์˜์—ญ์€ VB๋งŒํผ ์ด๋™ํ•  ๊ฒƒ์ด๋‹ค.
ํšŒ์ƒ‰ ์˜์—ญ์€ "Collision cone"์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
Collision cone์€ ๊ณ„์‚ฐํ• ๋•Œ A์™€ B์˜ ๋ฐ˜์ง€๋ฆ„์„ ๋”ํ•œ ์›์— ๋Œ€ํ•ด์„œ ์™ธ๊ณฝ์„ ์ง€๋‚˜๋Š” ์„  2๊ฐœ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌํ•œ๋‹ค.
 
๋”ฐ๋ผ์„œ, A์˜ Velocity๋ฅผ ์กฐ์ ˆํ•  ๋•Œ VB๋งŒํผ ์ด๋™ํ•œ ํšŒ์ƒ‰ ์˜์—ญ VO๋ฅผ ์นจ๋ฒ”ํ•˜์ง€ ์•Š๋Š” Velocity๋ฅผ ์กฐ์ ˆํ•˜๋ฉด ๋‹ค์Œ ํ”„๋ ˆ์ž„์—์„œ A๋Š” B๋ฅผ ํ”ผํ•ด์„œ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ๊ฒƒ์ด๋‹ค.

๋”ฐ๋ผ์„œ ๊ธฐ์กด์˜ VA ์†๋„๋ฅผ VO๋ฅผ ํ”ผํ•ด์„œ ๋นจ๊ฐ„์ƒ‰ ๋ถ€๋ถ„๋งŒํผ์œผ๋กœ ์กฐ์ •ํ•˜๋ฉด์„œ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ง„ํ–‰์‹œํ‚ค๋ฉด ์ถฉ๋Œ์„ ํšŒํ”ผํ•˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์ œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

VO์˜ ์ง„๋™ ํ˜„์ƒ์„ ์ค„์ธ RVO

 

Reciprocal Velocity Obstacle(RVO) : RVO2

์ƒˆ๋กœ์šด ๊ฐœ๋…์ธ Reciprocal Velocity Obstacle(์ดํ•˜ RVO)๋ฅผ ์ œ์•ˆํ•จ ๊ฐ ์—์ด์ „ํŠธ๊ฐ€ ๋‹ค๋ฅธ ์—์ด์ „ํŠธ์™€ ๋ช…์‹œ์ ์œผ๋กœ ํ†ต์‹ ํ•˜์ง€ ์•Š๊ณ  ๋…๋ฆฝ์ ์œผ๋กœ ์›€์ง์ด๋Š” ๊ฒฝ์šฐ๋ฅผ ๊ณ ๋ คํ•จ ์›€์ง์ด๋Š” ์žฅ์• ๋ฌผ๋“ค ์‚ฌ์ด์—์„œ์˜ ์›€์ง์ž„์„

dana3711.tistory.com

 


 
velocity obstacle ๊ด€๋ จ ์ž๋ฃŒ : https://en.wikipedia.org/wiki/Velocity_obstacle

๋…ผ๋ฌธ ์ฐธ๊ณ  : Motion Planning in Dynamic Environments using Velocity Obstacles - 1998๋…„๋„ ๋ฐœํ–‰ 

 

 

 

 

 

 

 

๋ฐ˜์‘ํ˜•

'๊ณต๋ถ€ > Crowd Simulation' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Reciprocal Velocity Obstacle(RVO) : RVO2  (0) 2020.01.21
728x90

๋ฒ„๋ธ”์ •๋ ฌ์„ ์ด์šฉํ•˜์—ฌ ๋žญํ‚น ์‹œ์Šคํ…œ์„ c++๋กœ ๊ตฌํ˜„ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์•ž์œผ๋กœ ๊ฒŒ์ž„์„ ์งค๋•Œ ๋žญํ‚น ์‹œ์Šคํ…œ์— ์ข…์ข… ์ด์šฉํ•  ์ˆ˜ ์žˆ๊ฒ ๊ตฐ์š”

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include<iostream>
#include<string>
using namespace std;
 
int main() {
    string array[10][2];
    string temp[1][2];// ๊ฐ’์˜ ์œ„์น˜๊ตํ™˜์— ์‚ฌ์šฉ ๋  ๋ณ€์ˆ˜
 
                      /*๋ฐฐ์—ด ์ดˆ๊ธฐํ™”*/
    for (int i = 0; i < 10; i++) { // ํ–‰
        array[i][0= { "___ " }; // ์—ด
        array[i][1= { "0" };
    }
    for (int j = 0; j < 9; j++)
    {
        for (int i = j; i < 9; i++)                    //๊ฐ’์ด ๊ทธ ๋‹ค์Œ๊ฐ’๋ถ€ํ„ฐ ๋“ค์–ด๊ฐ€์•ผํ•˜๋ฏ€๋กœ
        {
            cout << "์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”:";
            cin >> array[i][0];
            cout << "์ ์ˆ˜๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”:";
            cin >> array[i][1];
 
            for (int y = 9; y > 0; y--){
                for (int z = 0; z < y; z++) {
                    if (atoi(array[z][1].c_str()) < atoi(array[z + 1][1].c_str())) {
                        /*์ ์ˆ˜๋ถ€๋ถ„ ๋ณต์‚ฌ*/
                        temp[0][1= array[z][1];
                        array[z][1= array[z + 1][1];
                        array[z + 1][1= temp[0][1];
 
                        /*์ด๋ฆ„๋ถ€๋ถ„ ๋ณต์‚ฌ*/
                        temp[0][0= array[z][0];
                        array[z][0= array[z + 1][0];
                        array[z + 1][0= temp[0][0];
                    }
                }
            }
            cout << "-์ ์ˆ˜ ๋žญํ‚น-" << endl;
            for (i = 0; i < 10; i++) {
                cout << i + 1 << "  " << array[i][0<< "  " << array[i][1<< endl;
            }
            cout << endl;
        }
    }
    return 0;
}
 
cs
๋ฐ˜์‘ํ˜•
728x90

sweep and prune์€ ๊ต์ˆ˜๋‹˜๊ป˜์„œ ํŠน์ • ๋…ผ๋ฌธ์„ ์ฝ์œผ๋ผ๊ณ  ํ•˜์…จ์„ ๋•Œ ๋ณธ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค

ํ•˜์ง€๋งŒ ํ•œ๊ธ€ ํ•ด์„์ด ๋œ ํฌ์ŠคํŒ…์ด ์—†์–ด์„œ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋ฒˆ์—ญํ•˜์—ฌ ๋†“๊ณ  ์ ์  ์ถ”๊ฐ€ ๋ฐ ๋ณด์™„ํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค

ํ•ด๋‹น ํฌ์ŠคํŒ…์€ https://github.com/mattleibow/jitterphysics/wiki/Sweep-and-Prune ์„ ํ•œ๊ตญ์–ด๋กœ ํ•ด์„ํ•œ ํฌ์ŠคํŒ…์œผ๋กœ ๋ฌธ์ œ๊ฐ€๋  ์‹œ ์‚ญ์ œํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค

 

 

 

๊ด‘์—ญ ์ถฉ๋Œ ์‹œ์Šคํ…œ์€ ๋ชจ๋“  ๋ฌผ๋ฆฌ ์—”์ง„์˜ ํ•ต์‹ฌ ๊ณผ์ • ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

์ด๋ฏธ ๊ด‘์—ญ ์ถฉ๋Œ์— ๋Œ€ํ•ด ๋†“์นœ ๊ฒŒ ์žˆ๋‹ค๋ฉด ๊ด‘์—ญ ์ถฉ๋Œ์‹œ์Šคํ…œ์„ ์ตœ์ ํ™”ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์งœ์„œ ๋ณต๊ตฌํ•˜๊ธฐ๋Š” ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ฆฌ ์—”์ง„์—์„œ ์ถฉ๋Œ ๋‹จ๊ณ„์—๋Š” 3๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

1. Broadphase : ๊ด‘๋Œ€ํ•œ ๋ฒ”์œ„

- ์—ฌ๊ธฐ์„œ ์–ด๋–ค ์ถฉ๋Œ์ด ์‹ค์ œ๋กœ ์ผ์–ด๋‚  ์ˆ˜ ์žˆ๋Š”์ง€๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ์ถฉ๋Œํ•  ์ˆ˜ ์—†๋Š” ์ถฉ๋Œ์„ ํ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

 

์ฐธ๊ณ ํ• ๋งŒํ•œ ์‚ฌ์ดํŠธ : https://developer.nvidia.com/gpugems/gpugems3/part-v-physics-simulation/chapter-32-broad-phase-collision-detection-cuda

 

Chapter 32. Broad-Phase Collision Detection with CUDA

Chapter 32. Broad-Phase Collision Detection with CUDA Scott Le Grand NVIDIA Corporation Collision detection among many 3D objects is an important component of physics simulation, computer-aided design, molecular modeling, and other applications. Most effic

developer.nvidia.com

 

2. Midphase : ์ค‘๊ฐ„ ๋ฒ”์œ„

- ๊ตฌ๋‚˜ ์ฒœ ๋ฌผ์ฒด ๊ฐ™์€ ๊ธฐํ•˜ํ•™์  ๋‹จ๊ณ„์—์„œ์˜ ์ถฉ๋Œ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. 

 

3. Narrowphase : ์ข์€ ๋ฒ”์œ„

- ์ด ๋‹จ๊ณ„์—์„œ ์‹ค์ œ ์ถฉ๋Œ ๊ฐ์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.  ๊ต์ฐจ์ , ์ถฉ๋Œ ๋ฒ•์„  ๋˜๋Š” ์นจํˆฌ ๊นŠ์ด์™€ ๊ฐ™์€ ์ถฉ๋Œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ์ž‘์—…์„ ํ•ฉ๋‹ˆ๋‹ค.

 

๊ฑฐ์˜ ๋ชจ๋“  ๊ด‘์—ญ ์‹œ์Šคํ…œ์€ ๊ฐ์ฒด์˜ ์ถ• ์ •๋ ฌ๋œ ๊ฒฝ๊ณ„ ์ƒ์ž(aabb)๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

aabb๋Š” ๊ฝค ๋นจ๋ฆฌ ๊ณ„์‚ฐ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ต์ฐจ์ ์„ ํ™•์ธํ•˜๋Š” ๊ฒƒ๋„ ๋ช‡ ์ค„์˜ ์ฝ”๋“œ๋กœ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.

 

์ฐธ๊ณ ํ• ๋งŒํ•œ ์‚ฌ์ดํŠธ : https://blog.naver.com/mycode333/50031266282

 

AABB์™€ AABB ์ถฉ๋Œ

AABB( Axis Aligned Bounding Box)๋Š” ์ถ•์— ์ •๋ ฌ๋œ ์ƒํƒœ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ•์Šค๊ฐ€ ํšŒ์ „ํ•˜์ง€ ์•Š๊ณ  ์ถ• ๋ฐฉํ–ฅ...

blog.naver.com

 

๊ทธ๋ ‡๋‹ค๋ฉด, ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด "๊ฒน์น˜์ง€ ์•Š๋Š” ์Œ์˜ ์ •๋ ฌ ๊ณผ์ •"์„ ๊ฐ€์†ํ™” ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

์ถฉ๋Œ์„ ๊ฐ์ง€ํ•˜๊ธฐ ์œ„ํ•œ ์˜ˆ์ „์˜ ์ ‘๊ทผ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋ช‡ ๊ฐ€์ง€๋ฅผ ์•Œ์•„๋ด…์‹œ๋‹ค.

 

for (int i = 0; I < rigidBodies.Count; i++)
{
    for (int e = i; e < rigidBodies.Count; e++)
    {
        if (CheckBoundingBoxForOverlap(i, e))
            DetectNarrowPhase(i,e);
    }
}

 

๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ๋“ค์— ๋Œ€ํ•ด ์ฒซ ๋ฒˆ์งธ Rigidbody๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ์ฒซ ๋ฒˆ์งธ Rigidbody๋ฅผ ์ œ์™ธํ•œ ๋‹ค๋ฅธ ๋ชจ๋“  ๊ฒƒ๋“ค์— ๋Œ€ํ•ด ๋‘ ๋ฒˆ์งธ Rigidbody๋ฅผ ๊ฐ์ง€ํ•ฉ๋‹ˆ๋‹ค.

 

๊ทธ๋ ‡๊ฒŒ ๋‚˜์˜์ง€๋Š” ์•Š์ง€๋งŒ..

๋งŒ์•ฝ 10x10x10 ์ถฉ๋Œ ๊ฐ์ง€ ๋˜๋Š” ํ๋ธŒ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ตœ์ƒ์˜ ๊ฒฝ์šฐ ์ˆ˜์ฒœ ๊ฐœ์˜ ์ถฉ๋Œ ๊ฐ€๋Šฅํ•œ ์Œ์„ ํ™•์ธํ•˜์—ฌ ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ข์€ ๋ฒ”์œ„์˜ ์ถฉ๋Œ ์ฒดํฌ๋Š” 0.25๋ฐฑ๋งŒ ๊ฐœ๋ฅผ ์ฒดํฌํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

์ž์—ฐ์ ์œผ๋กœ ๊ด‘์—ญ ๋ฒ”์œ„๋Š” O(n^2) ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๋Š”๋ฐ ์ด์— ๋Œ€ํ•ด ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

 

๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์†ํ™”ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์›น์—์„œ "๊ด‘์—ญ์ƒ ์ถฉ๋Œ ํƒ์ง€"๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋ฉด Sweep And Prune(SAP)์ ‘๊ทผ๋ฒ•์„ ๋ฐœ๊ฒฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋งŽ์€ ๋ณ€ํ˜•๋œ ๊ตฌํ˜„๋“ค์ด ์žˆ์ง€๋งŒ ๋ถ„๋ฅ˜ํ•œ ๋‹ค์Œ ๋‹ค๋“ฌ๋Š”๋‹ค(Prune)๋Š” ๊ณตํ†ต์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

SAP ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ "flavor"๋ฅผ ์ง€์†๋˜์ง€ ์•Š๋Š” ๋‹จ์ผ ์ถ• SAP์—์„œ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์•Œ์•„๋ด…์‹œ๋‹ค.

 

1. ๊ณต๊ฐ„ ์•ˆ์˜ ๋ชจ๋“  ๋ฌผ์ฒด๋“ค์€ "AxisList"๋ผ๋Š” ๋ชฉ๋ก ์•ˆ์— ๋“ค์–ด์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฝ๊ณ„์ƒ์ž์˜ ์‹œ์ž‘์„ ์ด์šฉํ•ด ํ•œ ๊ฐœ์˜ ์ถ•(์—ฌ๊ธฐ์„œ๋Š” X์ถ•)์œผ๋กœ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฌผ์ฒด 5์˜ ๊ฐ€์žฅ ์™ผ์ชฝ ์ง€์ ์ด X์ถ•์„ ์ง์ ‘ ๋ณผ ๋•Œ ๋ฌผ์ฒด 6์˜ ๊ฐ€์žฅ ์™ผ์ชฝ ์ง€์ ๋ณด๋‹ค ๋” ์™ผ์ชฝ์— ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

2. "ActiveList"๋ผ๋Š” ์ƒˆ๋กœ์šด ์ž„์‹œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์ž. ์ด์ œ "AxisList"์˜ ๋‹ค์Œ ํ•ญ๋ชฉ์„ ๋ณด๊ณ  "ActiveList"์˜ ๋ชจ๋“  ํ•ญ๋ชฉ๊ณผ ๋น„๊ตํ•ฉ๋‹ˆ๋‹ค.(ํ˜„์žฌ๋Š” ๋‹จ ํ•˜๋‚˜) ๋งŒ์•ฝ ์ƒˆ ํ•ญ๋ชฉ์˜ ์™ผ์ชฝ์ด ๋” ํฌ๋ฉด ํ˜„์žฌ "ActiveList"์˜ ์˜ค๋ฅธ์ชฝ ํ•ญ๋ชฉ์ด ์ œ๊ฑฐ๋˜๊ณ  "ActiveList"์—์„œ ํ˜„์žฌ "ActiveList" ์•„์ดํ…œ์ด ์ œ๊ฑฐ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ƒˆ "AxisList" ํ•ญ๋ชฉ๊ณผ ํ˜„์žฌ "ActiveList" ํ•ญ๋ชฉ ๊ฐ„์˜ ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์ด ์ƒ๊น๋‹ˆ๋‹ค. ์ƒˆ ํ•ญ๋ชฉ ์ž์ฒด๋ฅผ "ActiveList"์— ์ถ”๊ฐ€ํ•˜๊ณ  "AxisList"์˜ ๋‹ค์Œ ํ•ญ๋ชฉ์„ ๊ณ„์†ํ•ฉ๋‹ˆ๋‹ค.

 

 

์ถœ์ฒ˜ : https://github.com/mattleibow/jitterphysics/wiki/Sweep-and-Prune

 

์ด ์ ‘๊ทผ๋ฒ•์ด ์ง€์†์ ์ด์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋ฉ๋‹ˆ๋‹ค.

์ •๋ ฌ์€ ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ชจ๋“  ํ”„๋ ˆ์ž„์—์„œ ์ˆ˜ํ–‰๋˜๋ฉฐ(quicksort ์„ฑ๋Šฅ์ด ์ข‹๋‹ค) ํ•œ ์ถ•(์—ฌ๊ธฐ์—์„œ๋Š” X์ถ•)์— ๋Œ€ํ•ด ์ •๋ ฌ๋œ๋‹ค.

์šฐ๋ฆฌ๋Š” ์žฅ๋ฉด์˜ ์ผ๊ด€์„ฑ์„ ์ด์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.(ํ•œ ํ”„๋ ˆ์ž„์—์„œ ์žฅ๋ฉด์ด ๋งŽ์ด ๋ณ€ํ•˜์ง€ ์•Š์„ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค)

์†๋„ ํ–ฅ์ƒ์€ ์–ด๋””์„œ ๋ฐœ์ƒํ•˜๋Š”๊ฒƒ์ผ๊นŒ?

์ •๋‹ต์€ ์ถฉ๋Œ ํƒ์ง€๋Š” ๊ฒ€์ƒ‰ ๋ฌธ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‚ฌ์ „ ๋ถ„๋ฅ˜๋œ ๋ชฉ๋ก์„ ๊ฒ€์ƒ‰์€ O(nlog(n)) ๋ณด๋‹ค ๋น ๋ฆ…๋‹ˆ๋‹ค.

์ด ์‰ฌ์šด ์ ‘๊ทผ๋ฒ•์„ ๊ตฌํ˜„ํ•˜๋ฉด ๋ฌด์ฐจ๋ณ„ ํž˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜(brute force algorithm)์— ๋น„ํ•ด ์—„์ฒญ๋‚œ ์†๋„ ํ–ฅ์ƒ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

JigLib (Danny Chapman์ด ๋งŒ๋“  ์ฝ”๋“œ)์—์„œ C # (JigLibX)๋กœ ์ด์‹๋˜์—ˆ์„ ๋•Œ, JigLib์˜ ์›๋ž˜ ๋ฒ„์ „์€ ๋ฌด์ฐจ๋ณ„์ ์ธ ํž˜๊ณผ ๋งค์šฐ ๊ธฐ๋ณธ์ ์ธ ๊ทธ๋ฆฌ๋“œ ์ ‘๊ทผ๋ฒ•์„ ํฌํ•จํ•˜๊ณ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
์กด ์™€ํŠธ๋Š” ์œ„์—์„œ ์„ค๋ช…ํ•œ ์ฝ”๋“œ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ์ ํŠธ์— SAP ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ ์šฉํ–ˆ๋Š”๋ฐ, ์ด๋Š” ๋ณต์žกํ•œ ๊ทธ๋ฆฌ๋“œ ์ ‘๊ทผ๋ฒ•์„ ์‰ฝ๊ฒŒ ๊ทน๋ณตํ–ˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ์ด ์ฝ”๋“œ๋Š” ์ด๋ฏธ ๊ฝค ์ž˜ ์ˆ˜ํ–‰๋˜์ง€๋งŒ, ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  X์ถ•์—์„œ ๋ชจ๋“  ๋ฌผ์ฒด๊ฐ€ ๊ฒน์น˜๋ฉด ๋Ÿฐํƒ€์ž„์€ ๋‹ค์‹œ O (n *2)์ด๋‹ค.

(๋”ฐ๋ผ์„œ, ๋Œ€๋ถ€๋ถ„์˜ ๋ฌผ์ฒด๊ฐ€ ๊ทธ๊ณณ์—์„œ ๊ฒน์น˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ถ„๋ฆฌ ์ถ•์œผ๋กœ up-์ถ•์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค)

 

Sweep and Prune์„ ํ•˜๊ธฐ ์œ„ํ•œ ๋” ๋ณต์žกํ•œ(๊ทธ๋ฆฌ๊ณ  ๋” ๋น ๋ฅธ) ์ ‘๊ทผ๋ฒ•์€ ์™„์ „ํ•œ 3์ถ• ๊ฒ€์‚ฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‘ ๋ฌผ์ฒด๊ฐ€ ์ถฉ๋Œํ•˜๋ฉด ์„ธ ์ถ• ๋ชจ๋‘ ๊ฒน์น˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค (๋ถ„๋ฆฌ ์ถ• ์ •๋ฆฌ).

์ง€์†์  3Axis SAP๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์š”์•ฝํ•˜์—ฌ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์„ธ ๊ฐœ์˜ ๋ชฉ๋ก (๊ฐ ์ถ• 1์— ๋Œ€ํ•ด)์„ ์‚ฌ์šฉํ•˜๊ณ  ์‚ฝ์ž… ์ •๋ ฌ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ •๋ ฌ๋œ ๋ชฉ๋ก์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

์‚ฝ์ž… ์ •๋ ฌ์€ ๊ฑฐ์˜ ์ •๋ ฌ๋œ ๋ชฉ๋ก์—์„œ O(n)์ž…๋‹ˆ๋‹ค.

์‚ฝ์ž… ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์Šค์™‘์€ ๊ฐœ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๋ณธ์ฒด์™€ ์ค‘์ฒฉ๋˜๊ธฐ ์‹œ์ž‘/์ค‘์ง€ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ํ•œ ๊ฐœ์˜ ํ•ด์‹œ ํ…Œ์ด๋ธ”์„ ๊ฒน์ณ์„œ ๋ณด๊ด€ํ•˜๊ณ , ๊ฐ ํ”„๋ ˆ์ž„์€ ์‚ฝ์ž…๊ตฌ์—ญ์„ ํ•˜๊ณ , ํ•ด์‹œ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ๋ณ€๊ฒฝ์‚ฌํ•ญ๋งŒ ๋ณด๊ณ ๋ฐ›์Šต๋‹ˆ๋‹ค.

 

 

Jitter์˜ ์ ˆ์ฐจ

private void SortAxis(List<SweepPoint> axis)
{
    for (int j = 1; j < axis.Count; j++)
    {
        SweepPoint keyelement = axis[j];
        float key = keyelement.Value;
        
        int i = j - 1;
        
        while (i >= 0 && axis[i].Value > key)
        {
            SweepPoint swapper = axis[i];
            
            if (keyelement.Begin && !swapper.Begin)
            {
                if (CheckBoundingBoxes(swapper.Body, keyelement.Body))
                {
                    lock (fullOverlaps)
                    {
                        fullOverlaps.Add(new BroadphasePair(swapper.Body, keyelement.Body));
                    }
                }
            }
            
            if (!keyelement.Begin && swapper.Begin)
            {
                lock (fullOverlaps) 
                {
                    fullOverlaps.Remove(new BroadphasePair(swapper.Body, keyelement.Body));
                }
            }
            
            axis[i + 1] = swapper;
            i = i - 1;
        }
        axis[i + 1] = keyelement;
    }
}
 

 

๋งŒ์•ฝ ๋‹น์‹ ์ด ์ „ํ˜•์ ์ธ SAP ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ์˜ ๋ชจ๋“  ์„ธ๋ถ€์‚ฌํ•ญ์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด, ๋‚˜๋Š” ํ”ผ์—๋ฅด ํ…Œ๋ฅด๋””๋งŒ์ด ์“ด ํ›Œ๋ฅญํ•œ ๊ธฐ์‚ฌ๋ฅผ ์ฝ์„ ๊ฒƒ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๊ฐ ํ”„๋ ˆ์ž„์— "A๊ฐ€ ์ถ• C์—์„œ B์™€ ๊ฒน์นœ๋‹ค"๋Š” ์ •๋ณด๋‚˜ "A๊ฐ€ ์ถ• C์—์„œ B์˜ ์ค‘์ฒฉ์„ ์ค‘์ง€ํ–ˆ๋‹ค"๋Š” ์ •๋ณด๋งŒ ์ „๋‹ฌ๋ฐ›์œผ๋ฉด X, Y ๋˜๋Š” Z์ถ•์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒ˜์Œ ์ด๊ฒƒ์„ ์‹œํ–‰ํ–ˆ์„ ๋•Œ, ๋‚˜๋Š” ๋‚ด๊ฐ€ ๋ฐ›๋Š” ๊ฐ’์‹ผ ๊ฒฐ๊ณผ์— ๋งค์šฐ ๋งŒ์กฑํ–ˆ๊ณ , ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ์‹ค์ˆ˜๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ์˜ ์Œ์ด ์–ผ๋งˆ๋‚˜ ์ค‘๋ณต๋˜๋Š”์ง€๋ฅผ ๊ธฐ์–ตํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฒน์น˜๋Š” ํšŸ์ˆ˜๊ฐ€ 3ํšŒ(๋ชจ๋“  ์ถ•์—์„œ ๊ฒน์น˜๋Š” ํšŸ์ˆ˜๊ฐ€ 1ํšŒ์ž„์„ ์˜๋ฏธ)์ธ ๊ฒฝ์šฐ, ๋ฌผ์ฒด๋Š” ์ถฉ๋Œํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ํšจ๊ณผ๊ฐ€ ์žˆ์ง€๋งŒ ๋”์ฐํ•ฉ๋‹ˆ๋‹ค.

ํ•œ ์ถ•์— ๊ฒน์น˜๋Š” ์Œ์˜ ์ˆ˜๋Š” ๋งค์šฐ ๋†’์„ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ค‘๋ณต ๊ณ„์ˆ˜ = 1์ธ ์ˆ˜์ฒœ ๊ฐœ์˜ ์ž ์žฌ์  ๊ฒน์น˜๋Š” ์Œ์„ ์ €์žฅํ•ด์•ผ ํ•œ๋‹ค. ๋‹จ์ง€ ๋ช‡ ๊ฐœ๋งŒ ๋‘ ๋ฒˆ์งธ ์ถ•์— ๊ฒน์น˜๊ณ  ๊ฒน์น˜๋Š” ํšŸ์ˆ˜๊ฐ€ 2์ด๊ณ , ์„ธ ๋ฒˆ์งธ ์ถ•์— ๊ฒน์น˜๋Š” ํšŸ์ˆ˜๋Š” 3์ด๋ผ๋Š” ๊ฒƒ์„ ๊นจ๋‹ฌ์•˜์Šต๋‹ˆ๋‹ค.

๊ฒฐ๊ตญ ๋Ÿฐํƒ€์ž„์€ O(nlogn)์˜€์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์€ O(n^2)์ด์—ˆ๋‹ค(๋‚ด ์‚ฌ์ „ ๊ตฌ์กฐ๋ฅผ ์ฃฝ์ด๋Š” ๊ฒƒ)

์ด ๋ฌธ์ œ์˜ ํ•ด๊ฒฐ์ฑ…์€ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค. ์•„๋ฌด๊ฒƒ๋„ ์ €์žฅํ•˜์ง€ ๋งˆ๋ผ.

ํ•œ ์ถ•์ด ์ค‘์ฒฉ์„ ๋ณด๊ณ ํ•˜๋Š” ๊ฒฝ์šฐ ์ €๋ ดํ•œ ์ „์ฒด ๊ฒฝ๊ณ„ ์ƒ์ž ํ™•์ธ – ์–‘์ˆ˜์ผ ๊ฒฝ์šฐ ํ•ด๋‹น ์Œ์„ ํ’€์˜ค๋ฒ„๋žฉ์— ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค.

ํ•œ ์ถ•์— ๋‘ ๊ฐœ์˜ ๋ชธ์ฒด๊ฐ€ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๋‹ค๊ณ  ๋ณด๊ณ ๋œ ๊ฒฝ์šฐ, ํ’€์˜ค๋ฒ„๋žฉ์—์„œ ์Œ์„ ์ œ๊ฑฐํ•˜์‹ญ์‹œ์˜ค. (์ด๊ฒƒ์€ ์œ„์˜ ์ฝ”๋“œ๋กœ ํ–‰ํ•ด์ง„๋‹ค.) ๋”ฐ๋ผ์„œ SAP์— ์‚ฌ์šฉ๋˜๋Š” ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋‹ค์‹œ O(n)์— ์ง€๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

("CollisionSystemPersistent"์—์„œ Jitter์˜ ๊ตฌํ˜„์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Œ) SAP.cs".)

 

์ง€์†์ ์ธ Sweep and Prune ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ๋‹จ์  ์ค‘ ํ•˜๋‚˜๋Š” ๋งŽ์€ ๋น„ํ™œ์„ฑ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง„ ์ •๋ง ํฐ ์„ธ๊ณ„๋ฅผ ๊ฒฝํ—˜ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ด์•Œ์ด ์ •์ ์ธ ๋ฌผ์ฒด๊ฐ€ ๋งŽ์€ ๋งˆ์„์„ ๊ด€ํ†ตํ•˜๋Š” ๊ฒƒ์„ ์ƒ์ƒํ•ด๋ณด๋ผ.

๊ฐ ๋ฌผ์ฒด(์ดํƒ„์œผ๋กœ๋ถ€ํ„ฐ ์ˆ˜๋งˆ์ผ ๋–จ์–ด์ ธ ์žˆ์–ด๋„)์™€ ํƒ„ํ™˜ ์ž์ฒด ์‚ฌ์ด์— ๊ตํ™˜์ด ์žˆ๋‹ค

์ด ๋ฌธ์ œ๋Š” ๊ทธ๋ฆฌ๋“œ(๊ด‘๋ฒ”์œ„ ๋‹จ๊ณ„)๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์†Œํ˜• SAP๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‚ด๊ฐ€ ์•Œ์•„์ฐจ๋ฆฐ ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๋Š” ๊ด‘์„ ๊ณผ ๊ฒฝ๊ณ„ ์ƒ์ž ์งˆ์˜๊ฐ€ ํšจ์œจ์ ์œผ๋กœ ์ˆ˜ํ–‰๋  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

๋ ˆ์ด์บ์ŠคํŒ…์˜ ๊ฒฝ์šฐ, ์ •๋ ฌ๋œ ์„ธ ๊ฐœ์˜ ๋ชฉ๋ก์€ ๊ท ์ผํ•˜์ง€ ์•Š์€ ๋ณต์…€ ๊ทธ๋ฆฌ๋“œ๋กœ ํ•ด์„๋  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ฃผ๋ฌธํ•œ ๋ ˆ์ด ์ฟผ๋ฆฌ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

์ด๊ฒƒ์€ ์‹ค์ œ๋กœ๋Š” ๋‹ค์†Œ ๋Š๋ฆฌ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ๋งŽ์€ ๋ณต์…€ ๊ทธ๋ฆฌ๋“œ๊ฐ€ ๋น„์–ด ์žˆ๊ณ  ์ดˆ๊ธฐ ํƒ€๊ฒฉ์„ ๋ฐ›์€ ๊ด‘์„ ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์ผ ๋ฟ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋‹จ์ง€ ๊ฐ ๋ฌผ์ฒด์— ๋Œ€ํ•ด ๊ฑฐ์นœ ํž˜ ๊ฒ€์‚ฌ๋ฅผ ํ•˜๋Š” ๊ฒƒ์ด ์ข…์ข… ๋” ๋น ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๋Š” ์žฅ๋ฉด์— ํ•˜๋‚˜์˜ ํฐ ๋ฌผ์ฒด(๋Œ€๊ฐœ ์ง€๋ฉด์ด๋‚˜ ๋ ˆ๋ฒจ)๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
์ด ๊ฐœ์ฒด์˜ ๋์ ์€ ์™„์ „ํžˆ ์™ผ์ชฝ์— ์žˆ๊ณ  ๋ชฉ๋ก ์˜ค๋ฅธ์ชฝ์— ์žˆ๋‹ค.

์Šค์œ„ํ”„ ํฌ์ธํŠธ์— ์ €์žฅ๋œ ์ถ”๊ฐ€ ์ •๋ณด๊ฐ€ ์—†์œผ๋ฉด ๊ฐœ์ฒด๊ฐ€ ํ›จ์”ฌ ๋” ํฐ ์—”ํ‹ฐํ‹ฐ์˜ ๋์ ์— ์˜ํ•ด ๋‘˜๋Ÿฌ์‹ธ์ด๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํšจ์œจ์ ์œผ๋กœ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†๋‹ค.

 

 

 

 

๋ฐ˜์‘ํ˜•
728x90

 

์ƒˆ ํ”„๋กœ์ ํŠธ๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ์ž!

 

 

์ด๋Ÿฐ ์ฐฝ์ด ๋œจ๋ฉด Win32 ์ฝœ์†” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค๊ฒƒ์ด๋‹ค.

์ด๋ฆ„์„ ๋ฐ”๊ฟ”์ฃผ๋ฉด ํ”„๋กœ์ ํŠธ์˜ ์ด๋ฆ„์ด ๋ฐ”๋€Œ๊ณ  ์œ„์น˜๋Š” ์ž์‹ ์ด ์„ค์ •ํ•ด์ฃผ๊ณ  ์‹ถ์€ ๊ณณ์— ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

(์ฐธ๊ณ ๋กœ ์ด๋ฆ„๊ณผ ์†”๋ฃจ์…˜ ์ด๋ฆ„์€ ๋™์ผํ•˜๊ฒŒ ์ž๋™์œผ๋กœ ์ž…๋ ฅ๋œ๋‹ค.)

 

ํ™•์ธ์„ ๋ˆ„๋ฅด๊ณ  ๊ทธ๋‹ค์Œ ๋œจ๋Š” ์ฐฝ์—์„œ ๋‹ค์Œ์„ ๋˜ ๋ˆŒ๋Ÿฌ์ฃผ์ž.

 

 

์ด๋Ÿฌํ•œ ์ฐฝ์ด ๋œจ๊ฒŒ ๋˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋งŒ๋“ค๊ณ  ์‹ถ์€ ๊ฒƒ์€ ๋นˆ ํ”„๋กœ์ ํŠธ์ด๊ธฐ์— ๋นˆํ”„๋กœ์ ํŠธ๋ฅผ ์ฒดํฌํ•˜๊ณ  ๋งˆ์นจ์„ ๋ˆŒ๋Ÿฌ์ฃผ๋ฉด ์ƒ์„ฑ๋œ๋‹ค.

 

 

์ž ๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ์†”๋ฃจ์…˜ ํƒ์ƒ‰๊ธฐ์— ๋‚ด๊ฐ€ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ๊ฐ€ ๋œจ๊ฒŒ ๋˜๋Š”๋ฐ ์—ฌ๊ธฐ์—์„œ

 

[์†Œ์ŠคํŒŒ์ผ] ์šฐํด๋ฆญ -> ์ถ”๊ฐ€ -> ์ƒˆ ํ•ญ๋ชฉ ์„ ๋ˆŒ๋Ÿฌ์ฃผ์ž

 

 

๊ทธ๋Ÿฌ๋ฉด ์ด๋Ÿฌํ•œ ์ฐฝ์ด ๋œจ๊ฒŒ ๋˜๋Š”๋ฐ

 

C++ ํŒŒ์ผ ์„ ํด๋ฆญํ•ด๋†“๊ณ  ์ด๋ฅธ์—๋Š” ์†Œ์Šค์ด๋ฆ„(์†Œ์Šค์ด๋ฆ„์€ ๊ผญ ์˜์–ด๋กœ ๋งŒ๋“ค๋„๋ก ํ•˜์ž).c ๋ฅผ ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

์†Œ์Šค์ด๋ฆ„.cpp ํŒŒ์ผ์„ ๋งŒ๋“ค๊ฒŒ ๋˜๋ฉด C์–ธ์–ด๊ฐ€ ์•„๋‹Œ C++์–ธ์–ด๋กœ ๋งŒ๋“ค์–ด์ง€๋ฏ€๋กœ ํ™•์žฅ์ž๋Š” ๊ผญ .c๋กœ ๋งŒ๋“ค์–ด์ฃผ๋„๋ก ํ•˜์ž.

 

 

์•ผ์ƒ์˜ ๋นˆ ์†Œ์ŠคํŒŒ์ผ์ด ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์กŒ๋‹ค!

 

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ์ˆ˜ํ•™์˜ ์ง‘ํ•ฉ๋‹จ์›๊ณผ ๊ฐ™์€ C์–ธ์–ด์˜ Hello,World! ์ถœ๋ ฅํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ํ•œ๋ฒˆ ๋งŒ๋“ค์–ด๋ณด์ž.

 

 

์ด๋ ‡๊ฒŒ ์ ์—ˆ์œผ๋ฉด Ctrl+F5 ๋ฒˆ์„ ๋ˆŒ๋Ÿฌ์„œ ์†”๋ฃจ์…˜์„ ๋นŒ๋“œํ•ด๋ณด์ž.

 

 

์ด๋Ÿฐ ์ฐฝ์ด ๋–ณ๋‹ค๋ฉด ์„ฑ๊ณตํ•œ๊ฒƒ์ด๋‹ค. (ํ•œ๊ธ€ ์œˆ๋„์šฐ์—์„œ๋Š” "๊ณ„์†ํ•˜๋ ค๋ฉด ์•„๋ฌด ํ‚ค๋‚˜ ๋ˆ„๋ฅด์‹ญ์‹œ์˜ค..." ์ผ๊ฒƒ์ด๋‹ค.)

 

 

ํ•œ๊ธ€์„ ์ ์–ด๋„ ์ž˜ ์ถœ๋ ฅ๋œ๋‹ค.

 

์Œ ๊ทธ๋Ÿฐ๋ฐ ์—ฌ๊ธฐ์„œ ์ฐฝ์˜ ์ƒ‰๊น”์ด ํฐ์ƒ‰์ธ๊ฒŒ ๋งˆ์Œ์— ์•ˆ๋“ ๋‹ค ์‹ถ์œผ๋ฉด ์ฐฝ์—์„œ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ์„ ํ•˜๋ฉด

 

 

์—ฌ๊ธฐ์„œ Properties(์†์„ฑ)์— ๋“ค์–ด๊ฐ€๋ณด์ž.

 

 

์—ฌ๊ธฐ์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์†์„ฑ์„ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

 

 

์ด๋ ‡๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค!

 

 

๋ฐ˜์‘ํ˜•
728x90

*C์–ธ์–ด๋Š” ์ ˆ์ฐจ์ง€ํ–ฅ์  ํŠน์„ฑ์„ ์ง€๋‹Œ๋‹ค.

C์–ธ์–ด๋Š” ์ •ํ•ด์ง„ ์ˆœ์„œ์˜ ์‹คํ–‰ํ๋ฆ„์„ ์ค‘์‹œํ•œ๋‹ค. ์ ˆ์ฐจ์ง€ํ–ฅ์ ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฒ˜์Œ ์ ‘ํ•˜๋Š” ์‚ฌ๋žŒ๋„ ์กฐ๊ธˆ๋งŒ ๊ณต๋ถ€ํ•˜๋ฉด ์‰ฝ๊ฒŒ ์ต์ˆ™ํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

 

*C์–ธ์–ด๋กœ ๊ตฌํ˜„๋œ ํ”„๋กœ๊ทธ๋žจ์€ ์ข‹์€ ์„ฑ๋Šฅ์„ ๋ณด์ธ๋‹ค.

์‚ฌ์šฉํ•˜๋Š” ๋ฉ”๋ชจ๋ฆฌ์˜ ์–‘์ด ์ƒ๋Œ€์ ์œผ๋กœ ์ ๊ณ , ์†๋„๋ฅผ ์ €ํ•˜์‹œํ‚ค๋Š” ์š”์†Œ๋“ค์„ ์ตœ์†Œํ™”ํ•œ ์–ธ์–ด์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

๋ฐ˜์‘ํ˜•
728x90

๊นŒ๋จน์ง€ ๋ง๊ณ  ๋ณต์Šตํ•˜์ž STL์€ ๊ฝค๋‚˜ ์œ ์šฉํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

๊ฐ„๋‹จํ•˜๊ฒŒ ์„ค๋ช…ํ•˜์ž๋ฉด STL์€ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์ž‘์„ฑ๋œ ๋งŽ์€ ์ œ๋„ค๋ฆญ ํด๋ž˜์Šค์™€ ํ•จ์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

์ปจํ…Œ์ด๋„ˆ,iterator,์•Œ๊ณ ๋ฆฌ์ฆ˜๋กœ ๋ถ„๋ฅ˜๋œ๋‹ค.

 

- ์ปจํ…Œ์ด๋„ˆ ์ข…๋ฅ˜

 ํด๋ž˜์Šค

ํ—ค๋” 

 vector

<vector> 

deque

<deque> 

list

<list> 

set

<set> 

map

<map> 

 stack

<stack> 

 queue

<queue> 

- iterator ์ข…๋ฅ˜

 ์ข…๋ฅ˜

iterator 

 const_iterator

 reverse_iterator

 const_reverse_iterator

- ์•Œ๊ณ ๋ฆฌ์ฆ˜

copy 

 merge

 random

 rotate

 equal

 min

 remove

 search

 find

 move

 replace

 sort

 max 

partition

 reverse

 swap

 

๋ฐ˜์‘ํ˜•

+ Recent posts