ahn heejong

๋‚˜์˜ ๋ฒ„๊ฑด๋”” ํŒ”๋ฉด์ฒด : Three.js๋ฅผ ์‚ฌ์šฉํ•œ 3D ๊ทธ๋ž˜ํ”ฝ์Šค ์ž…๋ฌธ๊ธฐ

2017-07-10
three.js
๊ทธ๋ž˜ํ”ฝ์Šค
์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ

๋“ค์–ด๊ฐ€๋ฉฐ

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

Stripe Radar

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

๊ทธ๋ž˜์„œ ์ง€๋‚œ ์ฃผ๋ง๋™์•ˆ ํ•œ ๋ฒˆ ๋„์ „ ํ•ด ๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค. ์ฃผ์ œ๋Š” ์ฃผ๋ง ๋™์•ˆ ahnheejong.name ๋Œ€๋ฌธ์— 3D๋กœ ๊ตฌํ˜„ํ•œ ๋‹ค๋ฉด์ฒด ๋„์šฐ๊ธฐ ์˜€๋‹ค. ์ด ๊ธ€์„ ๋ณด๊ณ  ์žˆ๋‹ค๋ฉด ์ด๋ฏธ ๋ณด์•˜๊ฒ ์ง€๋งŒ, ์•„๋ž˜๊ฐ€ ๋‚˜์˜ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ์ด๋‹ค. ๐Ÿ˜Ž

์ตœ์ข… ๊ฒฐ๊ณผ๋ฌผ

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


Three.js?

The aim of the project is to create an easy to use, lightweight, 3D library.

three.js๋Š” mr.doob ์ด๋ผ๋Š” ๋‹‰๋„ค์ž„์œผ๋กœ ํ™œ๋™ํ•˜๋Š” ์œ ์ €๊ฐ€ ๋งŒ๋“  3D ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค. ์›น์ƒ์—์„œ 3D ๊ทธ๋ž˜ํ”ฝ์„ ๊ฐ–๊ณ  ๋†€๊ธฐ ์œ„ํ•ด์„œ๋Š” HTML5 Canvas, WebGL, SVG, ํ”Œ๋ž˜์‹œ ๐Ÿ˜… ๋“ฑ์˜ ๋‹ค์–‘ํ•œ ์ˆ˜๋‹จ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, three.js๋Š” ์ด๋Ÿฐ ์—ฌ๋Ÿฌ ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ๋ฅผ ์‚ฌ์šฉํ•œ 3D ๊ทธ๋ž˜ํ”ฝ์„ ์ข€ ๋” ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ•œ ๋‹จ๊ณ„๋ฅผ ๊ฐ์‹ธ ๋†“์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ Wrapper ์—ญํ• ์„ ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๋‹ค.

ํšŒ์‚ฌ์—์„œ ๊ฐ™์ด ์ผ ํ•˜๋Š” ๋™๋ฃŒ๋ถ„ ์ค‘ ๊ทธ๋ž˜ํ”ฝ์Šค์— ๊ด€์‹ฌ๊ณผ ์กฐ์˜ˆ๊ฐ€ ๊นŠ์œผ์‹  ๋ถ„์ด ๊ณ„์…”์„œ 3D ๊ทธ๋ž˜ํ”ฝ์„ ํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค๋‹ˆ ์ด๋Ÿฐ ์ €๋Ÿฐ ํˆด์„ ์ถ”์ฒœํ•ด ์ฃผ์…จ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์ˆ˜๊ฐ€ ๋‚ด๊ฐ€ ์จ ๋ณธ ์  ์—†๋Š” GLSL์— ๊ธฐ๋ฐ˜ํ•˜๊ณ  ์žˆ๊ฑฐ๋‚˜, ๋งค์šฐ ๋‚ฎ์€ ์ถ”์ƒํ™” ๋‹จ๊ณ„์—์„œ HTML5 Canvas๋ฅผ ์ง์ ‘ ์กฐ์ž‘ํ•˜๋Š” ์‹์œผ๋กœ ์ž‘๋™ํ–ˆ๋‹ค. ์ปดํ“จํ„ฐ ๊ทธ๋ž˜ํ”ฝ์Šค์— ์žˆ์–ด ๋ฌธ์™ธํ•œ์ด๋ผ ์ตœ์ดˆ ํ•™์Šต ์ปค๋ธŒ๊ฐ€ ๋†’์€ ๊ธฐ์ˆ ๋กœ๋Š” ์˜๋ฏธ ์žˆ๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋‚ด๊ธฐ ์ „์— ์ง€์น  ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” API ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ–๊ณ  ์žˆ๊ณ , ์ต์ˆ™ํ•œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•ด (Canvas ์™€๋Š” ๋‹ค๋ฅด๊ฒŒ) ๋„ˆ๋ฌด ์ ˆ์ฐจ์ ์ด์ง€ ์•Š๊ฒŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋ผ ๊ธฐ๋Œ€๋˜๋Š” three.js๋ฅผ ์„ ํƒํ–ˆ๋‹ค.

3D ๊ทธ๋ž˜ํ”ฝ์˜ ๊ตฌ์„ฑ์š”์†Œ

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

๐Ÿˆ (์ถœ์ฒ˜:File:Felis catus-cat on snow.jpg - Wikimedia Commons)

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

๊ทธ๋ฆฌ๊ณ  ์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, ์‚ฌ์ง„์„ ์ฐ๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์ด๋Ÿฐ ์š”์†Œ๋“ค์€ ๊ฐ๊ฐ three.js์˜ ํŠน์ • ์š”์†Œ์™€ ๋Œ€์‘ํ•œ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ ์–ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  • ๊ณต๊ฐ„ - Scene
  • ํ”ผ์‚ฌ์ฒด : ๋ถ€ํ”ผ, ์งˆ๊ฐ - Mesh : Geometry, Material
  • ์นด๋ฉ”๋ผ - Camera
  • ๋น› - Light

๊ทธ๋Ÿผ ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ํŒ”๋ฉด์ฒด๋ฅผ ๊ทธ๋ ค์— ๋“ค์–ด๊ฐ€๊ธฐ์— ์•ž์„œ ๋‹ค์Œ์„ ๋ช…ํ™•ํžˆ ํ•˜๊ฒ ๋‹ค.

  • ๋‚˜๋Š” ์ปดํ“จํ„ฐ ๊ทธ๋ž˜ํ”ฝ์Šค์˜ ์ „๋ฌธ๊ฐ€๊ฐ€ ์•„๋‹ˆ๋‹ค. ์•ž์—์„œ ์–ธ๊ธ‰ ํ–ˆ๋“ฏ ์ด์ œ ๋ง‰ ์ฒซ ๋ฐœ์ž๊ตญ์„ ๋—€ ํ•™์ƒ์— ๋ถˆ๊ณผํ•˜๋‹ค. ๋‚ด๊ฐ€ ์ดํ•ดํ•œ ๋ฐ”๋ฅผ ํ‹€๋ฆฌ์ง€ ์•Š๊ฒŒ ์˜ฎ๊ธฐ๊ณ ์ž ๋…ธ๋ ฅํ•˜๊ฒ ์ง€๋งŒ, ํ‹€๋ฆฐ ๋ถ€๋ถ„์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค. ๋งŒ์•ฝ ๊ธ€์—์„œ ํ‹€๋ฆฐ ์ ์„ ๋ฐœ๊ฒฌํ•œ๋‹ค๋ฉด ๋ฉ”์ผ์„ ํ†ตํ•ด ์ œ๋ณดํ•ด ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ๋‹ค.
  • ์•„๋ž˜์˜ ๋‚ด์šฉ์€ 2017๋…„ 6์›” 27์ผ ๊ธฐ์ค€ ์ตœ์‹  ๋ฒ„์ „์ธ three.js r86 ๊ธฐ์ค€์œผ๋กœ ์“ฐ์—ฌ์กŒ๋‹ค.
  • ๋ชจ๋“  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋Š” ES2016 ๊ธฐ์ค€์œผ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค.

๊ทธ๋Ÿผ ์ด์ œ three.js๋กœ 3D ๊ทธ๋ž˜ํ”ฝ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž.


๊ณต๊ฐ„

๊ฐ€์žฅ ๋จผ์ €, ์šฐ๋ฆฌ์˜ ์˜ค๋ธŒ์ ํŠธ๋“ค์„ ๋†“์„ ๊ณต๊ฐ„์ด ํ•„์š”ํ•˜๋‹ค. three.js ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๊ณต๊ฐ„์„ Scene ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

Scenes allow you to set up what and where is to be rendered by three.js. This is where you place objects, lights and cameras.

const scene = new THREE.Scene();

Scene์€ ๋‹จ์–ด์˜ ๋œป ๊ทธ๋Œ€๋กœ ์šฐ๋ฆฌ๊ฐ€ ํ™”๋ฉด์— ๊ทธ๋ฆฌ๊ณ ์ž ํ•˜๋Š” ์–ด๋–ค ์žฅ๋ฉด์— ํ•ด๋‹นํ•œ๋‹ค. ๋ณด๋‹ค ์ •ํ™•ํ•˜๊ฒŒ๋Š”, ๊ทธ ์žฅ๋ฉด์— ๋Œ€ํ•œ ์ •๋ณด - ์นด๋ฉ”๋ผ๋Š” ์–ด๋””์„œ ์–ด๋–ค ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ”๋ผ๋ณด๊ณ  ์žˆ๊ณ , ๊ด‘์›์€ ์–ด๋””์— ์กด์žฌํ•˜๊ณ , ์–ด๋–ค ๋ฌผ์ฒด๋“ค์ด ์žˆ๊ณ  ๋“ฑ - ๋ฅผ ๋ชจ๋‘ ๋‹ด๊ณ  ์žˆ๋Š” ๋ฌด์–ธ๊ฐ€๋ผ๊ณ  ์ด์•ผ๊ธฐ ํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค. Scene ๊ณต์‹ ๋ฌธ์„œ

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

๊ทธ๋ฆผ์„ ๊ทธ๋ฆด ๋•Œ ๊ฐ™์€ ํ’๊ฒฝ์„ ๊ทธ๋ฆฌ๋”๋ผ๋„ ์œ ํ™”๋กœ ๊ทธ๋ฆด ์ˆ˜๋„, ์ˆ˜์ฑ„ํ™”๋กœ ๊ทธ๋ฆด ์ˆ˜๋„ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๋˜ํ•œ ์ข…์ด์— ๊ทธ๋ฆด ์ˆ˜๋„ ์žˆ๊ณ , ์ ํ† ์—, ์ฒ ํŒ์—, ์•„ํฌ๋ฆด ํŒ ์— ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๊ฐ™์€ ๊ทธ๋ฆผ์„ ๊ทธ๋ฆฌ๋”๋ผ๋„ ๋‹ค์–‘ํ•œ ์žฌ๋ฃŒ์™€ ์บ”๋ฒ„์Šค์— ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋“ฏ, (๊ฑฐ์น ๊ฒŒ ๋น„์œ ํ•˜์ž๋ฉด) ๊ฐ™์€ ๊ณต๊ฐ„Scene๋„ ๋‹ค์–‘ํ•œ ๊ธฐ์ˆ ์„ ์ด์šฉํ•ด ๊ทธ๋ ค๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ๋‚˜๋Š” ์›น์ƒ์˜ 3D ๊ทธ๋ž˜ํ”ฝ์Šค์—์„œ ๊ฐ€์žฅ ๋ณดํŽธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ํ‘œ์ค€ ๊ธฐ์ˆ ์ธ WebGL์ด๋ผ๋Š” ๊ธฐ์ˆ ์— ๊ธฐ๋ฐ˜ํ•œ ๋ Œ๋”๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

The WebGL renderer displays your beautifully crafted scenes using WebGL.

const renderer = new THREE.WebGLRenderer({
  alpha: true,
  antialias: true
})

WebGLRenderer ์ปจ์ŠคํŠธ๋Ÿญํ„ฐ๋Š” ์˜ต์…˜์˜ Object๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š”๋ฐ, ๋‚˜๋Š” ํˆฌ๋ช…ํ•œ ๋ฐฐ๊ฒฝ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๊ณ (alpha: true) ์•ˆํ‹ฐ์–ผ๋ผ์ด์–ด์‹ฑ์ด ์ ์šฉ๋œ(antialias: true) ํ™”๋ฉด์„ ๊ทธ๋ฆฌ๊ณ  ์‹ถ์—ˆ์œผ๋ฏ€๋กœ ํ•ด๋‹นํ•˜๋Š” ์˜ต์…˜์„ ์ฃผ์—ˆ๋‹ค. WebGLRenderer ๊ณต์‹ ๋ฌธ์„œ

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

ํ”ผ์‚ฌ์ฒด

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

  1. ์—ฌ๋Ÿ๊ฐœ์˜ ๋ฉด, ์—ฌ์„ฏ ๊ฐœ์˜ ๊ผญ์ง€์ , ์—ฌ๋Ÿ ๊ฐœ์˜ ๊ฐ„์„ ์„ ๊ฐ–๋Š” ๊ธฐํ•˜ํ•™์  ํ˜•ํƒœ
  2. ์ผ์ข…์˜ ๋ผˆ๋Œ€๋กœ์„œ ๊ธฐ๋Šฅํ•˜๋Š”, ๊ทธ ๊ธฐํ•˜ํ•™์  ํ˜•ํƒœ ์œ„์— ๋ง์”Œ์›Œ์ ธ ์‹ค์ œ๋กœ ์šฐ๋ฆฌ ๋ˆˆ์— ๋ณด์—ฌ์ง€๋Š” ์งˆ๊ฐ์„ ๊ฐ€์ง„ ํ‘œ๋ฉด

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

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

์ด๋Ÿฐ ์ด์œ ๋กœ, ๊ทธ๋ž˜ํ”ฝ์Šค์—์„œ๋Š” ์–ด๋–ค ๋ฌผ์ฒด๋ฅผ ๋ณดํ†ต ๋‘ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„์–ด ํ‘œํ˜„ํ•œ๋‹ค.

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

๊ทธ๋ฆฌ๊ณ  ์ด Geometry์— Material์ด ์ž…ํ˜€์ง„ ์˜ค๋ธŒ์ ํŠธ๋ฅผ three.js ์—์„œ๋Š” Mesh๋ผ ๋ถ€๋ฅธ๋‹ค. Mesh ๋ผ๋Š” ์šฉ์–ด์˜ ์ •ํ™•ํ•œ ํ•™๋ฌธ์ ์ธ ์˜๋ฏธ๊ฐ€ ๊ถ๊ธˆํ•ด์„œ ์ฐพ์•„๋„ ๋ณด๊ณ  ์ฃผ๋ณ€์— ๋ฌผ์–ด๋„ ๋ณด์•˜๋Š”๋ฐ, ์ •ํ™•ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋‹ค๊ธฐ๋ณด๋‹ค๋Š” ์–ด๋Š์ •๋„ ๊ด€์šฉ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ์šฉ์–ด์ธ ๋“ฏ ํ•œ๋‹ค. ์ดํ•˜ ๊ธ€์—์„œ๋Š” three.js ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋Œ€๋กœ Geometry ์™€ Material์˜ ํ•ฉ์„ Mesh๋ผ ๋ถ€๋ฅด๊ฒ ๋‹ค.

๋ฌผ์ฒด(Mesh) = ๋ผˆ๋Œ€(Geometry) + ํ‘œ๋ฉด(Material)

๊ทธ๋Ÿผ ์šฐ๋ฆฌ์˜ ํŒ”๋ฉด์ฒด ๋ฉ”์‰ฌ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž! ๋จผ์ € Geometry๊ฐ€ ํ•„์š”ํ•˜๋‹ค. 3D ๋ชจ๋ธ๋ง์˜ ๊ธฐ๋ณธ ๋‹จ์œ„๋Š” ์‚ผ๊ฐํ˜•์ด๋‹ค. ์ฆ‰, ๋ชจ๋“  ๋ฉด์€ ์‚ผ๊ฐํ˜•์˜ ํ•ฉ์œผ๋กœ ํ‘œํ˜„๋œ๋‹ค. ๊ตฌ์ฒด์™€ ๊ฐ™์€ ๋งค๋„๋Ÿฌ์šด ๋ฉด ์—ญ์‹œ ์ถฉ๋ถ„ํžˆ ์ž‘์€ ํฌ๊ธฐ์˜ ์‚ผ๊ฐํ˜•์„ ์ถฉ๋ถ„ํžˆ ๋งŽ์ด ๋ชจ์•„์„œ ํ‘œํ˜„ํ•ด ๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ์ˆ˜ํ•™์‹œ๊ฐ„์— ๋ณด์•˜๊ฒ ์ง€๋งŒ, ์ •์‚ผ๊ฐํ˜•์„ ์ •์‚ฌ๊ฐํ˜•, ์ •์œก๊ฐํ˜•, ์ •์ด์‹ญ๊ฐํ˜• ๋“ฑ์œผ๋กœ ์ ์  ๊ผญ์ง€์ ์˜ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ ค๊ฐ€๋‹ค๋ณด๋ฉด ๊ฒฐ๊ตญ ์›์— ๊ฐ€๊นŒ์›Œ์ง€๋Š” ์›๋ฆฌ์™€ ๊ฐ™๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด, 3D ๋ชจ๋ธ์˜ ๋ผˆ๋Œ€๋ฅผ ๋งŒ๋“ค์–ด๋‚ด๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ด๋‹ค.

  • ๊ผญ์ง€์ (Vertex)๋ฅผ ์ •์˜ํ•œ๋‹ค.
  • ์–ด๋–ค ์„ธ ๊ผญ์ง€์ ์ด ์ด์–ด์ ธ์„œ ์‚ผ๊ฐํ˜• ๋ฉด(Face)์„ ์ด๋ฃจ๋Š”์ง€๋ฅผ ์ •์˜ํ•œ๋‹ค.

์ด ์ž‘์—…์„ ์ฝ”๋“œ๋กœ ์˜ฎ๊ธฐ๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

const geometry = new THREE.Geometry();
geometry.vertices.push(
    new THREE.Vector3( -10,  10, 0 ),
    new THREE.Vector3( -10, -10, 0 ),
    new THREE.Vector3(  10, -10, 0 )
);

geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );

์œ„ ์ฝ”๋“œ๋Š” x-y ํ‰๋ฉด์— ์„ธ ์  (x= -10, y=10, x=-10, y=-10, x=10, y=-10)์„ ์ฐ์€ ํ›„ Geometry์˜ ์ฒซ ๋ฒˆ์งธ, ๋‘ ๋ฒˆ์งธ, ์„ธ ๋ฒˆ์งธ ์ ์„ ์ž‡๋Š” ๋ฉด์„ ์ถ”๊ฐ€ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

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

const RADIUS = 40
const geometry = new THREE.OctahedronGeometry(RADIUS, 0);

๊ธธ๊ฒŒ ์„ค๋ช…ํ•œ ๊ฒƒ์ด ๋ฌด์ƒ‰ํ•˜๋„๋ก ํ•œ ์ค„๋กœ ๋๋‚˜๋ฒ„๋ ธ๋‹ค ๐Ÿ˜… ์—ฌ๋‹ด์ด์ง€๋งŒ ์ง€๋‚œ ์ฃผ๋ง์— ์ž‘์—…์„ ํ•˜๋ฉฐ three.js๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ด๋Ÿฐ ๊ฐ„ํŽธํ•œ API ๋•๋ถ„์— ์˜๋ฏธ์žˆ๋Š” ๊ฒฐ๊ณผ๋ฌผ์„ ๋นจ๋ฆฌ ์ฐ์–ด๋‚ผ ์ˆ˜ ์žˆ๋Š” ์ ์ด ์ข‹๋‹ค๊ณ  ๋Š๊ผˆ๋‹ค. THREE.OctahedronGeometry๊ฐ€ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ์ธ์ž์˜ ์ข…๋ฅ˜์™€ ์˜๋ฏธ๋Š” ๊ณต์‹ ๋ฌธ์„œ์—์„œ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค.

Geometry๊ฐ€ ์ค€๋น„๋˜์—ˆ์œผ๋‹ˆ, Material์„ ์ค€๋น„ํ•  ์‹œ๊ฐ„์ด๋‹ค. ๋„์ž…๋ถ€์˜ ๋‹ค๋ฉด์ฒด๋ฅผ ๋ณด๋ฉด ๊ฐ„๋‹จํ•œ ์ˆ˜์ค€์ด๋‚˜๋งˆ ํšŒ์ „์— ๋”ฐ๋ผ ๊ฐ ํ‘œ๋ฉด์ด ๋น›์„ ๋” ๋ฐ›๊ฑฐ๋‚˜ ๋œ ๋ฐ›์œผ๋ฉด์„œ ๋ช…๋„๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์ž ์‹œ ํ›„ ๊ธ€์˜ ํ›„๋ฐ˜๋ถ€์—์„œ ๊ตฌํ˜„ํ•˜๊ธฐ๋กœ ํ•˜๊ณ , ์ผ๋‹จ ์ด ํŒŒํŠธ์—์„  ๋น›๊ณผ ์ƒํ˜ธ์ž‘์šฉ ํ•˜์ง€ ์•Š๋Š”, ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ํ‘œ๋ฉด์ธ MeshBasicMaterial์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค.

const material = new THREE.MeshBasicMaterial({ color: '#ff3030' })

๋งˆ์ง€๋ง‰์œผ๋กœ, ๋งŒ๋“ค์–ด ๋‚ธ Geometry์™€ Material ์„ ์ด์šฉํ•ด Mesh ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. Mesh์˜ ์ƒ์„ฑ์ž๋Š” (์˜ˆ์ƒํ–ˆ๊ฒ ๋“ฏ์ด) Geometry์™€ Material์˜ ๋‘ ์ธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค.

const mesh  = new THREE.Mesh(geometry, material)

์ด์ œ ๊ทธ๋ฆฌ๊ณ ์ž ํ•˜๋Š” ๋ฌผ์ฒด์˜ ์ค€๋น„๊ฐ€ ๋๋‚ฌ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ, ์•ž์„œ ์ค€๋น„ํ•œ ๊ณต๊ฐ„์— ์ด ๋ฌผ์ฒด๋ฅผ ๋†“์•„๋ณด์ž. ๊ธฐ๋ณธ์ ์œผ๋กœ scene.add ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ณต๊ฐ„์— ์ถ”๊ฐ€ํ•œ ๋ฌผ์ฒด๋Š” (0, 0, 0) ์œ„์น˜์— ๋†“์ธ๋‹ค. ๋‚˜์ค‘์— ๊ด€์ฐฐ์„ ์œ„ํ•ด ํŒ”๋ฉด์ฒด๋ฅผ ๊ณต๊ฐ„์— ๋†“์€ ํ›„์—๋Š” z์ถ•์—์„œ ๋’ค์ชฝ (ํ™”๋ฉด์„ ๋šซ๊ณ  ๋“ค์–ด๊ฐ€๋Š” ๋ฐฉํ–ฅ) ์œผ๋กœ ์•ฝ๊ฐ„ ๋ฐ€์–ด ๋‘์ž.

scene.add(mesh)
mesh.position.z = -RADIUS * 10

๊ณต๊ฐ„์ด ์žˆ๊ณ , ๋ฌผ์ฒด๊ฐ€ ์žˆ๋‹ค. ์ด์ œ ์นด๋ฉ”๋ผ๊ฐ€ ๋‚จ์•˜๋‹ค.

์นด๋ฉ”๋ผ

์ง€๊ธˆ๊นŒ์ง€์˜ ์š”์†Œ๋“ค์ด ๊ทธ๋žฌ๋“ฏ, three.js์˜ ์นด๋ฉ”๋ผ ์—ญ์‹œ ํ˜„์‹ค ์„ธ๊ณ„์˜ ์นด๋ฉ”๋ผ์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค. ๊ฐ™์€ ๊ณต๊ฐ„์— ๊ฐ™์€ ๋ฌผ์ฒด๋“ค์ด ๋ฐฐ์น˜๋˜์–ด ์žˆ์–ด๋„, ์–ด๋””์— ์„œ์„œ ์–ด๋–ค ์‹œ์„ ์œผ๋กœ ๋ฐ”๋ผ๋ณด๋Š๋ƒ์— ๋”ฐ๋ผ ๋ณด์ด๋Š” ํ’๊ฒฝ์ด ๋‹ค๋ฅผํ…๋ฐ, ์ด ์‹œ์„ ์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ์ด ์นด๋ฉ”๋ผ๋‹ค.

์—ฌ๊ธฐ์„œ๋Š” ์‹ค์ œ ์‚ฌ๋žŒ์˜ ๋ˆˆ ๋˜๋Š” ์นด๋ฉ”๋ผ ๋ Œ์ฆˆ์™€ ๋น„์Šทํ•˜๊ฒŒ ํˆฌ์‹œ ํˆฌ์˜)์„ ์‚ฌ์šฉํ•˜๋Š” PerspectiveCamera๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค. (PerspectiveCamera ์ด์™ธ์—๋„ ๋‹ค์–‘ํ•œ ํ˜•ํƒœ๋กœ Scene์„ ๋ฐ”๋ผ๋ณผ ์ˆ˜ ์žˆ๋Š” Camera๊ฐ€ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์ง€๋งŒ, ๋‚˜๋Š” ์•„์ง๊นŒ์ง€ ์‚ฌ์šฉ ํ•ด ๋ณด์ง€ ์•Š์•˜๋‹ค.) PerspectiveCamera๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

const FIELD_OF_VIEW = 20
const ASPECT = WIDTH / HEIGHT
const NEAR = 0.1
const FAR = 10000

const camera = new PerspectiveCamera(
  FIELD_OF_VIEW,
  ASPECT,
  NEAR,
  FAR
)

์ƒ์„ฑ์ž๊ฐ€ ๋ฐ›๋Š” ๋„ค ๊ฐœ์˜ ์ธ์ž๋Š” ๊ฐ๊ฐ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜๋ฏธ๋ฅผ ๊ฐ–๋Š”๋‹ค.

  • FIELD_OF_VIEW: ์นด๋ฉ”๋ผ์˜ ์‹œ์•ผ๊ฐ์„ ์˜๋ฏธํ•œ๋‹ค. ์ปค์งˆ ์ˆ˜๋ก ์นด๋ฉ”๋ผ๊ฐ€ ๋ฐ”๋ผ๋ณด๋Š” ์‹œ์•ผ๊ฐ์ด ๋„“์–ด์ง์„ ์˜๋ฏธํ•œ๋‹ค. ๋‹จ์œ„๋Š” degree.
  • ASPECT: ์‹œ์•ผ์˜ ๊ฐ€๋กœ์„ธ๋กœ๋น„๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ปจํ…Œ์ด๋„ˆ์˜ ๊ฐ€๋กœ์„ธ๋กœ๋น„์™€ ๋™์ผํ•œ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š”๊ฒŒ ์ข‹๋‹ค. ๋‹จ์œ„ ์—†์Œ.
  • NEAR: ๋ Œ๋”๋ง ํ•  ๋ฌผ์ฒด ๊ฑฐ๋ฆฌ์˜ ํ•˜ํ•œ๊ฐ’์œผ๋กœ, ๋„ˆ๋ฌด ๊ฐ€๊นŒ์ด ์žˆ๋Š” ๋ฌผ์ฒด๋ฅผ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ์นด๋ฉ”๋ผ๋กœ๋ถ€ํ„ฐ์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์ด ๊ฐ’๋ณด๋‹ค ์ž‘์€ ๋ฌผ์ฒด๋Š” ํ™”๋ฉด์— ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค. 0๋ณด๋‹ค ํฌ๊ณ  FAR ๋ณด๋‹ค ์ž‘์€ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • FAR: ๋ Œ๋”๋ง ํ•  ๋ฌผ์ฒด ๊ฑฐ๋ฆฌ์˜ ์ƒํ•œ๊ฐ’์œผ๋กœ, ๋„ˆ๋ฌด ๋ฉ€๋ฆฌ ์žˆ๋Š” ๋ฌผ์ฒด๋ฅผ ๊ทธ๋ฆฌ๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ์นด๋ฉ”๋ผ๋กœ๋ถ€ํ„ฐ์˜ ๊ฑฐ๋ฆฌ๊ฐ€ ์ด ๊ฐ’๋ณด๋‹ค ํฐ ๋ฌผ์ฒด๋Š” ํ™”๋ฉด์— ๊ทธ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค.

์ด์ œ ์ •๋ง ๋ชจ๋“  ์ค€๋น„๊ฐ€ ๋๋‚ฌ๋‹ค.

๊ทธ๋ ค๋‚ด๊ธฐ

์•ž์„œ ์ž ๊น ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด, ์ด ๋ชจ๋“  ์ •๋ณด๋ฅผ ์‹ค์ œ๋กœ ํ™”๋ฉด์— ๊ทธ๋ ค๋‚ด๋Š” ์ผ์€ renderer์˜ ์ผ์ด๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” #three ๋ผ๋Š” id๋ฅผ ๊ฐ–๋Š” <div>๋ฅผ ์ปจํ…Œ์ด๋„ˆ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ•˜๊ณ , ๊ฐ€๋กœ ์„ธ๋กœ๊ฐ€ 200px์ธ ๊ทธ๋ ค๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค. ๋จผ์ € ๋ Œ๋”๋Ÿฌ์˜ ๊ฐ€๋กœ ์„ธ๋กœ ๊ฐ’์„ ์ •ํ•ด์ฃผ์ž.

const WIDTH = 200
const HEIGHT = 200

renderer.setSize(WIDTH, HEIGHT)

๊ทธ ํ›„, ๋ Œ๋”๋Ÿฌ๊ฐ€ ๊ทธ๋ ค๋‚ธ ์žฅ๋ฉด์„ ๋‹ด์„ <canvas> ์—˜๋ฆฌ๋จผํŠธ๋ฅผ DOM ํŠธ๋ฆฌ์—์„œ ์ปจํ…Œ์ด๋„ˆ์˜ ์ž์‹์œผ๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค. ํ•ด๋‹น ์—˜๋ฆฌ๋จผํŠผ๋Š renderer.domElement ํ”„๋กœํผํ‹ฐ๋ฅผ ํ†ตํ•ด ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

const container = document.querySelector('#three')
container.appendChild(renderer.domElement)

๋งˆ์ง€๋ง‰์œผ๋กœ, ์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๋งŒ๋“ค์–ด๋†“์€ ์žฅ๋ฉด๊ณผ ์นด๋ฉ”๋ผ๋ฅผ ์ด์šฉํ•ด ํ™”๋ฉด์„ ์‹ค์ œ๋กœ ๊ทธ๋ฆฌ๋ผ๋Š” ๋ช…๋ น์„ ๋‚ด๋ฆฐ๋‹ค. ์ด ๋ช…๋ น์€ renderer.render ๋ฉ”์†Œ๋“œ๋ฅผ ์ด์šฉํ•œ๋‹ค.

renderer.render(scene, camera)

์—ฌ๊ธฐ๊นŒ์ง€ ๋ชจ๋“  ๊ณผ์ •์„ ๋”ฐ๋ผ์™”๋‹ค๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์€ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

๋„ˆ๋ฌด๋‚˜๋„ ์ƒˆ๋นจ๊ฐ„ ๊ทธ๋Œ€

์ง€๊ธˆ ํ•˜๊ณ  ์žˆ๋Š” ์ƒ๊ฐ์„ ๋งž์ถฐ๋ณด๊ฒ ๋‹ค:

์ด๊ฑด ํŒ”๋ฉด์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ๋งˆ๋ฆ„๋ชจ์ž–์•„ ๐Ÿ˜ณ

์ผ๋‹จ ๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด, ์ด๊ฑด ํŒ”๋ฉด์ฒด๊ฐ€ ๋งž๋‹ค. ์ •ํ™•ํžˆ ๋งํ•˜๋ฉด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€ ํŠน์ˆ˜ํ•œ ์ƒํ™ฉ์— ๋†“์—ฌ ์žˆ๋Š” ํŒ”๋ฉด์ฒด๋‹ค.

  • ํŒ”๋ฉด์ฒด์˜ ์ค‘์‹ฌ์€ (0, 0, -400)์— ๋†“์—ฌ ์žˆ๊ณ , ์นด๋ฉ”๋ผ๋Š” (0, 0, 0) ์— ๋†“์—ฌ ์žˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ •์˜ํ•œ ์นด๋ฉ”๋ผ์˜ ์‹œ์ ์€ z์ถ•์„ ๋”ฐ๋ผ ํŒ”๋ฉด์ฒด์˜ ์ •์ค‘์•™์„ ๋šซ๊ณ  ์ง€๋‚˜๊ฐ€๊ณ  ์žˆ๋‹ค.
  • MeshBasicMaterial์€ ๋น›๊ณผ ์ƒํ˜ธ์ž‘์šฉ์„ ํ•˜์ง€ ์•Š๋Š” Material ์ด๋ผ๊ณ  ํ–ˆ๋‹ค. ์‹ค์ œ๋กœ ์šฐ๋ฆฌ๋Š” ๊ณต๊ฐ„์— ๋น›์„ ์ •์˜์กฐ์ฐจ ํ•˜์ง€ ์•Š์•˜๋‹ค.

๋น›์˜ ๋ถ€์žฌ๋Š” ๊ณง ๊ณต๊ฐ„์—์„œ์˜ ์‹ฌ๋„์˜ ๋ถ€์žฌ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์‹ฌ๋„๊ฐ€ ์—†๋Š”, ์ฆ‰ ํ•œ ์ถ•์ด ๋ฌด์˜๋ฏธํ•ด์ง„ 3D๋Š” 2D๋กœ ๋‚˜ํƒ€๋‚œ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›ํ–ˆ๋˜ ๊ฒƒ์€ 2D ๊ฐ™์€ 3D๊ฐ€ ์•„๋‹ˆ๋ผ 3D๋‹ค์šด 3D์ด๋ฏ€๋กœ, ์ด์ œ ์ด ํŒ”๋ฉด์ฒด๋ฅผ ์‹ค์ œ๋กœ 3D ๊ณต๊ฐ„์˜ ๋ฌผ์ฒด์™€ ๊ฐ™์•„ ๋ณด์ด๋„๋ก ๋งŒ๋“ค์–ด ๋ณด์ž.


๋น›๊ณผ ์งˆ๊ฐ

๋จผ์ €, ์ด ๊ณต๊ฐ„์— ์‹ฌ๋„๋ฅผ ์‹ฌ์–ด๋ณด์ž. ์œ„์—์„œ ์ž ๊น ํžŒํŠธ๋ฅผ ์คฌ๋“ฏ์ด ์ด ์ž‘์—…์€ ๋‘ ๋‹จ๊ณ„๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

  • ๊ณต๊ฐ„์— ๋น›์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
  • ํŒ”๋ฉด์ฒด๊ฐ€ ๋น›๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋„๋ก ํ•œ๋‹ค.

๋จผ์ € ๋น›์„ ์ถ”๊ฐ€ํ•ด๋ณด์ž. ๋ชจ๋“  ๊ด‘์›์˜ ์ƒ์„ฑ์ž๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒ‰๊น”(color)์™€ ์„ธ๊ธฐ(intensity)์˜ ๋‘ ์ธ์ž๋ฅผ ๋ฐ›๋Š”๋‹ค. three.js๋Š” ๊ณต๊ฐ„ ์ „์ฒด๋ฅผ ๋ฐํžˆ๋Š” AmbientLight, ํŠน์ • ๋ฐฉํ–ฅ์œผ๋กœ ๋ป—์–ด๋‚˜๊ฐ€๋Š” DirectionalRight ๋“ฑ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๊ด‘์›์„ ์ œ๊ณตํ•œ๋‹ค. ์ด ๊ธ€์—์„œ๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ๊ด‘์› ์ค‘ ํ•˜๋‚˜์ธ PointLight๋ฅผ ์‚ฌ์šฉํ•˜๊ฒ ๋‹ค.

A light that gets emitted from a single point in all directions. A common use case for this is to replicate the light emitted from a bare lightbulb.

๊ณต์‹ ๋ฌธ์„œ์˜ ์„ค๋ช…์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ, PointLight๋Š” ๋งˆ์น˜ ์ „๊ตฌ์ฒ˜๋Ÿผ ํ•œ ์ ์—์„œ ์‹œ์ž‘ํ•ด ๋ชจ๋“  ๋ฐฉํ–ฅ์œผ๋กœ ๋ป—์–ด๋‚˜๊ฐ€๋Š” ๊ด‘์›์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.

const pointLight = new PointLight(0xFFFFFF, 0.5)

pointLight.position.x = 100
pointLight.position.y = 100
pointLight.position.z = 30

scene.add(pointLight)

๋ฐฑ์ƒ‰ ๊ด‘์„ ์ •์˜ํ•˜๊ณ , ์œ„์น˜๋ฅผ ์žก์•„์ค€ ๋’ค ๊ณต๊ฐ„์— ๋น›์„ ๋”ํ•œ๋‹ค. ์ด ์‹œ์ ์—์„œ๋Š” ํ™”๋ฉด์— ์•„๋ฌด๋Ÿฐ ๋ณ€ํ™”๊ฐ€ ์—†๋Š”๋ฐ, ์ด๋Š” ์•„์ง๊นŒ์ง€๋„ ํŒ”๋ฉด์ฒด์˜ ํ‘œ๋ฉด์ด ๋น›๊ณผ ์ƒํ˜ธ์ž‘์šฉ์„ ์ „ํ˜€ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด์ œ Material์„ ๋ณ€๊ฒฝ ํ•ด๋ณด์ž. ์ง์ž‘ํ–ˆ๊ฒ ์ง€๋งŒ, three.js ์—์„œ๋Š” ๋น›๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ํ‘œ๋ฉด ์ค‘ ์ž์ฃผ ์“ฐ์ด๋Š” ํ‘œ๋ฉด ๋ชจ๋ธ ๋ช‡ ๊ฐ€์ง€๋ฅผ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•œ๋‹ค. ๊ทธ ์ค‘ ์—ฌ๊ธฐ์—์„œ๋Š” ๋žŒ๋ฒ ๋ฅดํŠธ ๋ฐ˜์‚ฌ์œจ์„ ๊ฐ–๋Š” ๋ฌผ์ฒด์˜ ํ‘œ๋ฉด์„ ๋‚˜ํƒ€๋‚ด๋Š” MeshLambertMaterial๋ฅผ ์ด์šฉํ•ด๋ณด๊ฒ ๋‹ค. ๊ธฐ์กด์— ์ž‘์„ฑ๋œ ์ฝ”๋“œ์—์„œ material์˜ ์ •์˜๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด๋ณด์ž.

const material = new THREE.MeshLambertMaterial({ color: 0xFF3030 })

์ด์ œ ์•„๋ž˜์™€ ๊ฐ™์€ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์„ ๊ฒƒ์ด๋‹ค.

๊ฑฐ์˜ ์™„์„ฑ๋œ ๋ชจ์Šต

์•ž์„œ ์ƒ์„ฑํ•œ ๋น›์„ (100, 100, 30)์— ๋‘์—ˆ๋Š”๋ฐ, ์ด๋Š” ์šฐ์ธก ์ƒ๋‹จ, ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์•ฝ๊ฐ„ ๋šซ๊ณ  ๋‚˜์˜จ ๊ณณ์— ์œ„์น˜ํ•˜๋Š” ์ ์ด๋‹ค. ์‹ค์ œ๋กœ ๋” ๋งŽ์€ ๋น›์„ ๋ฐ›์„ ์šฐ์ธก ์ƒ๋‹จ์€ ๋” ๋ฐ์€ ์ƒ‰์„ ๊ฐ–๋Š” ๋ฐ˜๋ฉด ์ขŒ์ธก ํ•˜๋‹จ์€ ๋น›์„ ๊ฑฐ์˜ ๋ฐ›์ง€ ๋ชปํ•ด ๊นŒ๋งฃ๊ฒŒ ๋ณด์ด๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„์ง ๋‚˜ํ•œํ…Œ๋Š” ํ‰๋ฉด์œผ๋กœ ๋ณด์ด๋Š”๋ฐ?

๊ทธ๋Ÿผ ๋งˆ์ง€๋ง‰์œผ๋กœ ์ด ํŒ”๋ฉด์ฒด๊ฐ€ ์‚ผ์ฐจ์› ์ƒ์—์„œ ๊ทธ๋ ค์กŒ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด๋‹ค ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด, ํ•œ ๋ฒˆ ํšŒ์ „์‹œ์ผœ๋ณด์ž.

์›€์ง์ž„

๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” requestAnimationFrame ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ๋งค๋„๋Ÿฌ์šด ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๊ทธ๋ ค๋‚ผ ์ˆ˜ ์žˆ๋‹ค. ์ด ํ•จ์ˆ˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ณ , ํ•œ ํ”„๋ ˆ์ž„์„ ํ• ๋‹น๋ฐ›์•„์„œ ์ธ์ž๋กœ ๋ฐ›์€ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. ์•ž์„œ ์ ์—ˆ๋˜ renderer.render(scene, camera) ๋ผ์ธ์„ ๋‹ค์Œ์œผ๋กœ ๊ต์ฒดํ•œ๋‹ค.

function update () {
  const speed = Math.random() / 20
  octahedron.rotation.x += speed
  octahedron.rotation.y += speed
  octahedron.rotation.z += speed
  renderer.render(scene, camera)
  requestAnimationFrame(update)
}

requestAnimationFrame(update)

๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค 0 ~ 0.05 ์‚ฌ์ด์˜ ๊ฐ’์„ ์ž„์˜๋กœ ์ •ํ•œ ๋’ค, x, y, z ์ถ•๋งˆ๋‹ค ํ•ด๋‹น ๊ฐ’๋งŒํผ์˜ ํšŒ์ „์„ ์ค€๋‹ค. ๊ทธ ๋’ค์— scene์„ ๋‹ค์‹œ ๊ทธ๋ฆฌ๊ณ , ์ž๊ธฐ ์ž์‹ ์„ requestAnimationFrame ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋‹ค์‹œ ๋„˜๊ฒจ ํ˜ธ์ถœํ•˜๋Š” ๋‚ด์šฉ์ด๋‹ค.

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

์ „์ฒด ์ฝ”๋“œ์™€ ๋™์ž‘ํ•˜๋Š” ๋ชจ์Šต์€ ์ฝ”๋“œํŽœ์—์„œ ํ™•์ธํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค.


๋งบ์œผ๋ฉฐ

์ด ๊ธ€์„ ํ†ตํ•ด 3D ๊ทธ๋ž˜ํ”ฝ์Šค์— ๋Œ€ํ•ด ์ „ํ˜€ ๋ฌธ์™ธํ•œ์ด๋˜ ๋‚ด๊ฐ€ ํ™ˆํŽ˜์ด์ง€์— ํŒ”๋ฉด์ฒด๋ฅผ ๊ทธ๋ ค๋‚ด๊ธฐ๊นŒ์ง€์˜ ์—ฌ์ •์„ ์ „๋ถ€ ๋‹ด์•„ ๋ณด์•˜๋‹ค. ๋‚˜์™€ ๊ฐ™์€ ์œ„์น˜์— ์žˆ๋Š” ์‚ฌ๋žŒ์„ ์œ„ํ•ด ๋‚ด๊ฐ€ ๊ถ๊ธˆํ–ˆ๋˜ ์ ์„ ๋”ฐ๋กœ ์ฐพ์•„๋ณด์ง€ ์•Š์•„๋„ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ์ตœ๋Œ€ํ•œ ์ž์„ธํžˆ ์ ์œผ๋ ค ๋…ธ๋ ฅํ–ˆ๋Š”๋ฐ, ๊ทธ ๋•Œ๋ฌธ์— ๋„ˆ๋ฌด ์‰ฝ๊ณ  ์žฅํ™ฉํ•œ ๊ธ€์ด ๋˜์ง€๋Š” ์•Š์•˜๋Š”์ง€ ๊ฑฑ์ •๋„ ๋œ๋‹ค. ๊ฐœ์ธ์ ์œผ๋กœ๋Š” ๊ธ€์„ ์ ์œผ๋ฉด์„œ ์• ๋งคํ•˜๊ฒŒ ์•Œ๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋˜ ๊ฐœ๋…์„ ๋ณด๋‹ค ๊ฐ€๋‹ค๋“ฌ์„ ์ˆ˜ ์žˆ์–ด ์ข‹์•˜๋‹ค.

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

๋ฌด์—‡๋ณด๋‹ค๋„ ์Šค์Šค๋กœ ๋‚ด๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ, ๋˜ ๋‚ด๊ฐ€ ์žฌ๋ฏธ์žˆ๋‹ค๊ณ  ๋Š๋ผ๋Š” ์ผ์— ์„ฃ๋ถˆ๋ฆฌ ํ•œ๊ณ„๋ฅผ ์ •ํ•  ๋•Œ ๊ฒฐ๊ตญ ์†ํ•ด ๋ณด๋Š” ๊ฑด ๋‚˜๋ฟ์ด๋ผ๋Š” ๊ฐ„๋‹จํ•œ ์ด์น˜๋ฅผ ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ฒด๊ฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„

์ฃผ๋ง ๋™์•ˆ ๋‹ค๋ฉด์ฒด๋ฅผ ์˜ฌ๋ ค ๋ณด๊ฒ ๋‹ค๋Š” ๋ชฉํ‘œ ์ž์ฒด๋Š” ๋‹ฌ์„ฑํ–ˆ์ง€๋งŒ, ์ง€๊ธˆ ์ƒํƒœ๋Š” ์‹œ์ž‘์— ๋ถˆ๊ณผํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์•ž์œผ๋กœ ์‹œ๋„ํ•ด๋ณด๊ณ  ์‹ถ์€ ์ด๋Ÿฐ ์ €๋Ÿฐ ๋ชฉํ‘œ๋“ค์ด ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์ž๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ๋งˆ์šฐ์Šค / ํ„ฐ์น˜ ์ด๋ฒคํŠธ์— ์ ์ ˆํžˆ ๋ฐ˜์‘ํ•˜๋Š” ์ธํ„ฐ๋ž™์…˜ ์ถ”๊ฐ€
  • ํŒ”๋ฉด์ฒด๊ฐ€ ์‚ฌ๋ฉด์ฒด, ํ๋ธŒ ๋“ฑ์œผ๋กœ ๋ชจ์–‘์„ ๋ฐ”๊พธ์–ด๊ฐ€๋Š” ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€
  • ํ…์Šค์ณ๋ฅผ ์ž…ํžˆ๊ณ  ๋ณด๋‹ค ์ •๊ตํ•œ Material์„ ์ด์šฉํ•ด ๋‚˜๋ฌด, ์‡  ๊ฐ™์€ ๋Š๋‚Œ ๊ตฌํ˜„
  • ๊ทธ ์™ธ์— ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์œผ๋กœ ๋” ์ด์˜๊ฒŒ ๋งŒ๋“ค๊ธฐ

๋” ์ข‹์€ ์ƒ๊ฐ์ด ์žˆ์œผ๋ฉด ๋‚ด๊ฒŒ ์ œ๋ณด ํ•ด ์ค€๋‹ค๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ๋‹ค. ํ•œ ๋ฒˆ์— ์—„์ฒญ๋‚œ ๊ฒฉ๋ณ€์„ ์ด๋ฃจ์–ด๋‚ด๊ธฐ๋ณด๋‹ค ์ฒœ์ฒœํžˆ ์กฐ๊ทธ๋งŒ ๋ถ€๋ถ„์”ฉ ์‹คํ—˜ ํ•ด ๋ณผ ์ƒ๊ฐ์ด๋‹ค.

๊ฐ์‚ฌ์˜ ๋ง

๋งˆ์ง€๋ง‰์œผ๋กœ, three.js๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ณ  ํฐ ๋„์›€์„ ๋ฐ›์•˜๋˜ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŠธ์˜ ์ €์ž Paul Lewis, ๊ทธ๋ฆฌ๊ณ  ํ™ˆํŽ˜์ด์ง€์— ํŒ”๋ฉด์ฒด๋ฅผ ๊ทธ๋ฆฌ๊ณ  ๊ทธ ๊ณผ์ •์„ ์ด๋ ‡๊ฒŒ ๊ธ€๋กœ ์˜ฎ๊ธฐ๋ฉฐ ๋งŽ์€ ๊ฐ€๋ฅด์นจ๊ณผ ๋„์›€์„ ์ค€ ๊น€์ง€ํ˜„๊ณผ ์ตœ์ข…์ฐฌ์—๊ฒŒ ๊ฐ์‚ฌ๋ฅผ ์ „ํ•œ๋‹ค.


๊ธ€์„ ๊ณต์œ ํ•˜๊ณ ์ž ํ•˜์‹ค ๋•Œ์—๋Š” ๋ณธ๋ฌธ์„ ๋ณต์‚ฌ/๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•˜๋Š” ๋Œ€์‹  ๋งํฌ๋ฅผ ๋‚จ๊ฒจ์ฃผ์‹ญ์‹œ์˜ค. ์ด ๊ธ€์— ๋Œ€ํ•ด ๋‚จ๊ธฐ๊ณ  ์‹ถ์€ ์ฝ”๋ฉ˜ํŠธ๋‚˜ ์˜ค๋ฅ˜ ์ง€์ , ๊ธ€์“ด์ด์—๊ฒŒ ํ•˜๊ณ  ์‹ถ์€ ๋ง ๋“ฑ์€ ๋ฉ”์ผ์„ ํ†ตํ•ด ์ œ๋ณดํ•ด ์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ธด ๊ธ€์„ ์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.