WebXR ๊น์ด ๊ฐ์ง API ์๋ฒฝ ๊ฐ์ด๋๋ก ๊ณ ๊ธ ์ฆ๊ฐ ํ์ค์ ๊ตฌํํ์ธ์. ์ฌ์ค์ ์ธ ์คํด๋ฃจ์ ๊ณผ ๋ฌผ๋ฆฌ ํจ๊ณผ๋ฅผ ์ํ ๊น์ด ๋ฒํผ ๊ตฌ์ฑ๋ฒ์ ๋ฐฐ์๋ณด์ธ์.
WebXR ๊น์ด ๊ฐ์ง ์ฌ์ธต ๋ถ์: ๊น์ด ๋ฒํผ ๊ตฌ์ฑ ๋ง์คํฐํ๊ธฐ
์น์ 2์ฐจ์์ ์ธ ์ ๋ณด์ ํ๋ฉด์์ 3์ฐจ์์ ์ด๊ณ ๋ชฐ์ ๊ฐ ์๋ ๊ณต๊ฐ์ผ๋ก ์งํํ๊ณ ์์ต๋๋ค. ์ด ๋ณํ์ ์ ๋์๋ ๊ฐ์ ํ์ค๊ณผ ์ฆ๊ฐ ํ์ค์ ๋ธ๋ผ์ฐ์ ๋ก ๊ฐ์ ธ์ค๋ ๊ฐ๋ ฅํ API์ธ WebXR์ด ์์ต๋๋ค. ์น์์์ ์ด๊ธฐ AR ๊ฒฝํ์ ์ธ์์ ์ด์์ง๋ง, ์ข ์ข ํ์ค ์ธ๊ณ์ ๋จ์ ๋ ๋๋์ ์ฃผ์์ต๋๋ค. ๊ฐ์ ๊ฐ์ฒด๋ค์ ํ์ค ์ธ๊ณ์ ๊ฐ๊ตฌ๋ ๋ฒฝ์ ํต๊ณผํ๋ฉฐ ์กด์ฌ๊ฐ ์์ด ํ๊ณต์ ๋ ๋ค๋ ์ต๋๋ค.
WebXR ๊น์ด ๊ฐ์ง API(WebXR Depth Sensing API)๊ฐ ๋ฐ๋ก ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํฉ๋๋ค. ์ด ํ๊ธฐ์ ์ธ ๊ธฐ๋ฅ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ฌ์ฉ์ ํ๊ฒฝ์ ๊ธฐํํ์ ๊ตฌ์กฐ๋ฅผ ์ดํดํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ ๋น์ ์ธ ๋์ฝ์ ๋๋ค. ์ด๋ ๋์งํธ๊ณผ ๋ฌผ๋ฆฌ์ ์ธ๊ณ ์ฌ์ด์ ๊ฐ๊ทน์ ๋ฉ์, ๊ฐ์ ์ฝํ ์ธ ๊ฐ ํ์ค ์ธ๊ณ์ ๋ฒ์น๊ณผ ๋ฐฐ์น๋ฅผ ์กด์คํ๋ ์ง์ ์ผ๋ก ๋ชฐ์ ๊ฐ ์๊ณ ์ํธ์์ฉ์ ์ธ ๊ฒฝํ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ์ด ํ์ ๋ฐํํ๋ ์ด์ ๋ ๊น์ด ๋ฒํผ๋ฅผ ์ดํดํ๊ณ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑํ๋ ๋ฐ ์์ต๋๋ค.
์ด ํฌ๊ด์ ์ธ ๊ฐ์ด๋๋ ์ ์ธ๊ณ์ ์น ๊ฐ๋ฐ์, XR ์ ํธ๊ฐ, ํฌ๋ฆฌ์์ดํฐ๋ธ ๊ธฐ์ ์ ๋ฌธ๊ฐ๋ฅผ ์ํด ์ค๊ณ๋์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊น์ด ๊ฐ์ง์ ๊ธฐ๋ณธ ์๋ฆฌ๋ฅผ ํ๊ตฌํ๊ณ , WebXR API์ ๊ตฌ์ฑ ์ต์ ์ ๋ถ์ํ๋ฉฐ, ์ฌ์ค์ ์ธ ์คํด๋ฃจ์ ๋ฐ ๋ฌผ๋ฆฌ ํจ๊ณผ์ ๊ฐ์ ๊ณ ๊ธ AR ๊ธฐ๋ฅ์ ๊ตฌํํ๊ธฐ ์ํ ์ค์ฉ์ ์ด๊ณ ๋จ๊ณ์ ์ธ ์ง์นจ์ ์ ๊ณตํ ๊ฒ์ ๋๋ค. ์ด ๊ฐ์ด๋๋ฅผ ๋ง์น๋ฉด ๊น์ด ๋ฒํผ ๊ตฌ์ฑ์ ๋ง์คํฐํ๊ณ ์ฐจ์ธ๋ ์ค๊ฐ ๋๋ ์ํฉ ์ธ์ WebXR ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์๋ ์ง์์ ๊ฐ์ถ๊ฒ ๋ ๊ฒ์ ๋๋ค.
ํต์ฌ ๊ฐ๋ ์ดํดํ๊ธฐ
API์ ์ธ๋ถ ์ฌํญ์ ์ดํด๋ณด๊ธฐ ์ ์, ๊ฒฌ๊ณ ํ ๊ธฐ์ด๋ฅผ ๋ค์ง๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๊น์ด ์ธ์ ์ฆ๊ฐ ํ์ค์ ๊ฐ๋ฅํ๊ฒ ํ๋ ํต์ฌ ๊ฐ๋ ๋ค์ ๋ช ํํ ํด๋ด ์๋ค.
๊น์ด ๋งต(Depth Map)์ด๋ ๋ฌด์์ธ๊ฐ?
๋ฐฉ์ ๋ณด๊ณ ์๋ค๊ณ ์์ํด๋ณด์ธ์. ์ฌ๋ฌ๋ถ์ ๋๋ ํ ์ด๋ธ์ด ๋ฒฝ๋ณด๋ค ๊ฐ๊น๊ณ , ์์๊ฐ ํ ์ด๋ธ ์์ ์๋ค๋ ๊ฒ์ ์์ฝ๊ฒ ์ฒ๋ฆฌํฉ๋๋ค. ๊น์ด ๋งต์ ์ด๋ฌํ ์ดํด๋ฅผ ๋์งํธ๋ก ํํํ ๊ฒ์ ๋๋ค. ํต์ฌ์ ์ผ๋ก ๊น์ด ๋งต์ ๊ฐ ํฝ์ ์ ๊ฐ์ด ์์์ด ์๋๋ผ, ๋ฌผ๋ฆฌ์ ์ธ๊ณ์ ํด๋น ์ง์ ์ด ์ผ์(๊ธฐ๊ธฐ์ ์นด๋ฉ๋ผ)๋ก๋ถํฐ ๋จ์ด์ง ๊ฑฐ๋ฆฌ๋ฅผ ๋ํ๋ด๋ 2D ์ด๋ฏธ์ง์ ๋๋ค.
ํ์์กฐ ์ด๋ฏธ์ง๋ผ๊ณ ์๊ฐํ๋ฉด ๋ฉ๋๋ค. ์ด๋์ด ํฝ์ ์ ๋งค์ฐ ๊ฐ๊น์ด ๊ฐ์ฒด๋ฅผ, ๋ฐ์ ํฝ์ ์ ๋ฉ๋ฆฌ ์๋ ๊ฐ์ฒด๋ฅผ ๋ํ๋ผ ์ ์์ต๋๋ค(ํน์ ๊ด๋ก์ ๋ฐ๋ผ ๊ทธ ๋ฐ๋์ผ ์๋ ์์ต๋๋ค). ์ด ๋ฐ์ดํฐ๋ ์ผ๋ฐ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ํน์ ํ๋์จ์ด๋ฅผ ํตํด ์บก์ฒ๋ฉ๋๋ค:
- ToF(Time-of-Flight) ์ผ์: ์ด ์ผ์๋ ์ ์ธ์ ํ์ค๋ฅผ ๋ฐฉ์ถํ๊ณ ๋น์ด ๋ฌผ์ฒด์ ๋ฐ์ฌ๋์ด ๋์์ค๋ ๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ์ ์ธก์ ํฉ๋๋ค. ์ด ์๊ฐ ์ฐจ์ด๋ ์ง์ ์ ์ผ๋ก ๊ฑฐ๋ฆฌ๋ก ๋ณํ๋ฉ๋๋ค.
- LiDAR(Light Detection and Ranging): ToF์ ์ ์ฌํ์ง๋ง ์ข ์ข ๋ ์ ๋ฐํ๋ฉฐ, LiDAR๋ ๋ ์ด์ ํ์ค๋ฅผ ์ฌ์ฉํ์ฌ ํ๊ฒฝ์ ๊ณ ํด์๋ ํฌ์ธํธ ํด๋ผ์ฐ๋๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ ๊น์ด ๋งต์ผ๋ก ๋ณํํฉ๋๋ค.
- ์คํ ๋ ์ค์ค์ฝํฝ ์นด๋ฉ๋ผ: ๋ ๋ ์ด์์ ์นด๋ฉ๋ผ๋ฅผ ์ฌ์ฉํ์ฌ ๊ธฐ๊ธฐ๋ ์ธ๊ฐ์ ์์ ์๊ฐ์ ๋ชจ๋ฐฉํ ์ ์์ต๋๋ค. ๊ฐ ์นด๋ฉ๋ผ์์ ์ป์ ์ด๋ฏธ์ง ๊ฐ์ ์ฐจ์ด(์์ฐจ)๋ฅผ ๋ถ์ํ์ฌ ๊น์ด๋ฅผ ๊ณ์ฐํฉ๋๋ค.
WebXR API๋ ๊ธฐ๋ฐ ํ๋์จ์ด๋ฅผ ์ถ์ํํ์ฌ, ๊ฐ๋ฐ์์๊ฒ ๊ธฐ๊ธฐ์ ๊ด๊ณ์์ด ํ์คํ๋ ๊น์ด ๋งต์ ์ ๊ณตํฉ๋๋ค.
AR์์ ๊น์ด ๊ฐ์ง๊ฐ ์ค์ํ ์ด์ ๋ ๋ฌด์์ธ๊ฐ?
๋จ์ํ ๊น์ด ๋งต ํ๋๊ฐ ์ฌ์ฉ์์ AR ๊ฒฝํ์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ฐ๊พธ๋ ๋ฌดํํ ๊ฐ๋ฅ์ฑ์ ์ด์ด์ฃผ๋ฉฐ, ์ด๋ฅผ ๋จ์ํ ์ ๊ธฐํจ์์ ์ง์ ์ผ๋ก ๋ฏฟ์ ์ ์๋ ์ํธ์์ฉ์ผ๋ก ๊ฒฉ์์ํต๋๋ค.
- ์คํด๋ฃจ์ (Occlusion): ์ด๊ฒ์ ๋จ์ฐ์ฝ ๊ฐ์ฅ ์ค์ํ ์ด์ ์ ๋๋ค. ์คํด๋ฃจ์ ์ ํ์ค ์ธ๊ณ์ ๊ฐ์ฒด๊ฐ ๊ฐ์ ๊ฐ์ฒด์ ์์ผ๋ฅผ ๊ฐ๋ฆฌ๋ ๋ฅ๋ ฅ์ ๋๋ค. ๊น์ด ๋งต์ ์ฌ์ฉํ๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ํฝ์ ์์ ํ์ค ์ธ๊ณ ํ๋ฉด์ ์ ํํ ๊ฑฐ๋ฆฌ๋ฅผ ์ ์ ์์ต๋๋ค. ๋ ๋๋งํ๋ ค๋ ๊ฐ์ ๊ฐ์ฒด๊ฐ ๋์ผํ ํฝ์ ์ ํ์ค ์ธ๊ณ ํ๋ฉด๋ณด๋ค ๋ฉ๋ฆฌ ์๋ค๋ฉด, ๋จ์ํ ๊ทธ๋ฆฌ์ง ์๋๋ก ์ ํํ ์ ์์ต๋๋ค. ์ด ๊ฐ๋จํ ํ์๋ง์ผ๋ก ๊ฐ์ ์บ๋ฆญํฐ๊ฐ ์ค์ ์ํ ๋ค๋ก ์ค๋๋ ฅ ์๊ฒ ๊ฑธ์ด๊ฐ๊ฑฐ๋ ๋์งํธ ๊ณต์ด ์ค์ ํ ์ด๋ธ ์๋๋ก ๊ตด๋ฌ๊ฐ๋ ๋ฑ, ๊น์ ํตํฉ๊ฐ์ ๋ง๋ค์ด๋ ๋๋ค.
- ๋ฌผ๋ฆฌ ๋ฐ ์ํธ์์ฉ: ์ ์ ์ธ ๊ฐ์ ๊ฐ์ฒด๋ ํฅ๋ฏธ๋กญ์ง๋ง, ์ํธ์์ฉํ๋ ๊ฐ์ฒด๋ ๋งค๋ ฅ์ ์ ๋๋ค. ๊น์ด ๊ฐ์ง๋ ์ฌ์ค์ ์ธ ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ ์ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค. ๊ฐ์ ๊ณต์ด ์ค์ ๋ฐ๋ฅ์ ํ๊ธฐ๊ณ , ๋์งํธ ์บ๋ฆญํฐ๊ฐ ์ค์ ๊ฐ๊ตฌ๋ฅผ ํผํด ๋ค๋๋ฉฐ, ๊ฐ์ ํ์ธํธ๊ฐ ๋ฌผ๋ฆฌ์ ์ธ ๋ฒฝ์ ํฉ๋ฟ๋ ค์ง ์ ์์ต๋๋ค. ์ด๋ ์ญ๋์ ์ด๊ณ ๋ฐ์์ ์ธ ๊ฒฝํ์ ์ฐฝ์ถํฉ๋๋ค.
- ์ฅ๋ฉด ์ฌ๊ตฌ์ฑ(Scene Reconstruction): ์๊ฐ์ ๋ฐ๋ฅธ ๊น์ด ๋งต์ ๋ถ์ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ํ๊ฒฝ์ ๋จ์ํ๋ 3D ๋ฉ์๋ฅผ ๊ตฌ์ถํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ธฐํํ์ ์ดํด๋ ์ฌ์ค์ ์ธ ์กฐ๋ช (์ค์ ํ๋ฉด์ ๊ทธ๋ฆผ์ ๋๋ฆฌ์ฐ๊ธฐ) ๋ฐ ์ง๋ฅ์ ์ธ ๊ฐ์ฒด ๋ฐฐ์น(์ค์ ํ ์ด๋ธ ์์ ๊ฐ์ ํ๋ณ ๋๊ธฐ)์ ๊ฐ์ ๊ณ ๊ธ AR ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๋ฐ ํ์์ ์ ๋๋ค.
- ํฅ์๋ ํ์ค๊ฐ: ๊ถ๊ทน์ ์ผ๋ก, ์ด ๋ชจ๋ ๊ธฐ๋ฅ๋ค์ ๋ ์ฌ์ค์ ์ด๊ณ ๋ชฐ์ ๊ฐ ์๋ ๊ฒฝํ์ ๊ธฐ์ฌํฉ๋๋ค. ๋์งํธ ์ฝํ ์ธ ๊ฐ ์ฌ์ฉ์์ ๋ฌผ๋ฆฌ์ ๊ณต๊ฐ์ ์ธ์ํ๊ณ ์ํธ์์ฉํ ๋, ์ด๋ ํ์ค๊ณผ ๊ฐ์์ ์ฅ๋ฒฝ์ ํ๋ฌผ๊ณ ๋ ๊น์ ์กด์ฌ๊ฐ์ ์กฐ์ฑํฉ๋๋ค.
WebXR ๊น์ด ๊ฐ์ง API: ๊ฐ์
๊น์ด ๊ฐ์ง ๋ชจ๋์ ํต์ฌ WebXR ๋๋ฐ์ด์ค API์ ํ์ฅ ๊ธฐ๋ฅ์ ๋๋ค. ๋ง์ ์ต์ฒจ๋จ ์น ๊ธฐ์ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ์ฑํ๋์ด ์์ง ์์ ์ ์์ผ๋ฉฐ ํน์ ํ๋๊ทธ๊ฐ ํ์ํ๊ฑฐ๋ ์ค๋ฆฌ์ง ํธ๋ผ์ด์ผ(Origin Trial)์ ์ผ๋ถ์ผ ์ ์์ต๋๋ค. ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ ์ ํญ์ ์ง์ ์ฌ๋ถ๋ฅผ ํ์ธํ์ฌ ๋ฐฉ์ด์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
์ง์ ์ฌ๋ถ ํ์ธํ๊ธฐ
์ธ์ ์ ์์ฒญํ๊ธฐ ์ ์, ๋จผ์ ๋ธ๋ผ์ฐ์ ๊ฐ 'depth-sensing' ๊ธฐ๋ฅ๊ณผ ํจ๊ป 'immersive-ar' ๋ชจ๋๋ฅผ ์ง์ํ๋์ง ๋ฌผ์ด๋ด์ผ ํฉ๋๋ค. ์ด๋ `navigator.xr.isSessionSupported()` ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ํ๋ฉ๋๋ค.
async function checkDepthSensingSupport() {
if (!navigator.xr) {
console.log("WebXR is not available.");
return false;
}
try {
const supported = await navigator.xr.isSessionSupported('immersive-ar');
if (supported) {
// ์ด์ ํน์ ๊ธฐ๋ฅ์ ํ์ธํฉ๋๋ค
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['depth-sensing']
});
// ์ฑ๊ณตํ๋ฉด ๊ธฐ๋ฅ์ด ์ง์๋๋ ๊ฒ์
๋๋ค. ํ
์คํธ ์ธ์
์ ์ข
๋ฃํ ์ ์์ต๋๋ค.
await session.end();
console.log("WebXR AR with Depth Sensing is supported!");
return true;
} else {
console.log("WebXR AR is not supported on this device.");
return false;
}
} catch (error) {
console.log("Error checking for Depth Sensing support:", error);
return false;
}
}
๋ ์ง์ ์ ์ด์ง๋ง ๋ ์์ ํ ๋ฐฉ๋ฒ์ ์ธ์ ์ ์ง์ ์์ฒญํ๊ณ ์ค๋ฅ๋ฅผ ์ก๋ ๊ฒ์ด์ง๋ง, ์์ ๋ฐฉ๋ฒ์ด ์ฌ์ ์ ๊ธฐ๋ฅ์ ํ์ธํ๋ ๋ฐ ๋ ๊ฒฌ๊ณ ํฉ๋๋ค.
์ธ์ ์์ฒญํ๊ธฐ
์ง์์ ํ์ธํ ํ์๋ `requiredFeatures` ๋๋ `optionalFeatures` ๋ฐฐ์ด์ 'depth-sensing'์ ํฌํจํ์ฌ XR ์ธ์ ์ ์์ฒญํฉ๋๋ค. ํต์ฌ์ ๊ธฐ๋ฅ ์ด๋ฆ๊ณผ ํจ๊ป ๊ตฌ์ฑ ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ด๋ฉฐ, ์ฌ๊ธฐ์ ์ฐ๋ฆฌ์ ์ ํธ๋๋ฅผ ์ ์ํฉ๋๋ค.
async function startXRSession() {
const session = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['local-floor', 'dom-overlay'], // ๋ค๋ฅธ ์ผ๋ฐ์ ์ธ ๊ธฐ๋ฅ
optionalFeatures: [
{
name: 'depth-sensing',
usagePreference: ['cpu-optimized', 'gpu-optimized'],
dataFormatPreference: ['float32', 'luminance-alpha']
}
]
});
// ... ์ธ์
์ค์ ์งํ
}
'depth-sensing'์ด ์ด์ ๊ฐ์ฒด๋ผ๋ ์ ์ ์ฃผ๋ชฉํ์ธ์. ์ด๊ฒ์ด ๋ธ๋ผ์ฐ์ ์ ๊ตฌ์ฑ ํํธ๋ฅผ ์ ๊ณตํ๋ ๋ถ๋ถ์ ๋๋ค. ์ด ์ค์ํ ์ต์ ๋ค์ ๋ถ์ํด ๋ณด๊ฒ ์ต๋๋ค.
๊น์ด ๋ฒํผ ๊ตฌ์ฑ: ํต์ฌ ์ฌํญ
๊น์ด ๊ฐ์ง API์ ํ์ ์ ์ฐ์ฑ์ ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ์ ๊น์ด ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ ๊ฒ์ธ์ง ์๋ ค์ฃผ๋ฉด, ๋ธ๋ผ์ฐ์ ๋ ์ฌ์ฉ ์ฌ๋ก์ ๊ฐ์ฅ ํจ์จ์ ์ธ ํ์์ผ๋ก ์ ๋ณด๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด ๊ตฌ์ฑ์ ์ฃผ๋ก `usagePreference`์ `dataFormatPreference`๋ผ๋ ๋ ๊ฐ์ง ์์ฑ์ ํตํด ๊ธฐ๋ฅ ์ค๋ช ์ ๊ฐ์ฒด ๋ด์์ ์ด๋ฃจ์ด์ง๋๋ค.
`usagePreference`: CPU์ธ๊ฐ, GPU์ธ๊ฐ?
`usagePreference` ์์ฑ์ ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ฌ์ฉ์ ์์ด์ ํธ(User Agent, ์ฆ ๋ธ๋ผ์ฐ์ )์ ์๋ฆฌ๋ ๋ฌธ์์ด ๋ฐฐ์ด์ ๋๋ค. ์ด๋ฅผ ํตํด ์์คํ ์ ์ฑ๋ฅ, ์ ํ๋ ๋ฐ ์ ๋ ฅ ์๋น๋ฅผ ์ต์ ํํ ์ ์์ต๋๋ค. ์ฌ๋ฌ ์ฌ์ฉ๋ฒ์ ์ ํธ๋ ์์๋ก ์์ฒญํ ์ ์์ต๋๋ค.
'gpu-optimized'
- ์๋ฏธ: ๊น์ด ๋ฐ์ดํฐ๋ฅผ GPU์์ ์ง์ , ์ฃผ๋ก ๋ ๋๋ง ๋ชฉ์ ์ ์ ฐ์ด๋ ๋ด์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ฃผ๋ ๋ชฉํ์์ ๋ธ๋ผ์ฐ์ ์ ์๋ฆฝ๋๋ค.
- ๋ฐ์ดํฐ ์ ๊ณต ๋ฐฉ์: ๊น์ด ๋งต์ `WebGLTexture`๋ก ๋ ธ์ถ๋ฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ๋ ๋๋ง์ ์ฌ์ฉ๋๊ธฐ ์ํด GPU ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฒ์ด๋ ํ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋งค์ฐ ํจ์จ์ ์ ๋๋ค.
- ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก: ์คํด๋ฃจ์ . ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋์์ ์ด ํ ์ค์ฒ๋ฅผ ์ํ๋งํ์ฌ ์ค์ ์ธ๊ณ์ ๊น์ด์ ๊ฐ์ ๊ฐ์ฒด์ ๊น์ด๋ฅผ ๋น๊ตํ๊ณ , ์จ๊ฒจ์ ธ์ผ ํ ํ๋๊ทธ๋จผํธ๋ฅผ ํ๊ธฐํ ์ ์์ต๋๋ค. ์ด๋ ๊น์ด ์ธ์ ํํฐํด์ด๋ ์ฌ์ค์ ์ธ ๊ทธ๋ฆผ์์ ๊ฐ์ ๋ค๋ฅธ GPU ๊ธฐ๋ฐ ํจ๊ณผ์๋ ์ ์ฉํฉ๋๋ค.
- ์ฑ๋ฅ: ๋ ๋๋ง ์์ ์ ์์ด ์ต๊ณ ์ฑ๋ฅ ์ต์ ์ ๋๋ค. ๋งค ํ๋ ์๋ง๋ค GPU์์ CPU๋ก ๋๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ ์์ฒญ๋ ๋ณ๋ชฉ ํ์์ ํผํ ์ ์์ต๋๋ค.
'cpu-optimized'
- ์๋ฏธ: CPU์ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์์ ์์ ๊น์ด ๊ฐ์ ์ง์ ์ ๊ทผํด์ผ ํฉ๋๋ค.
- ๋ฐ์ดํฐ ์ ๊ณต ๋ฐฉ์: ๊น์ด ๋งต์ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ ๊ทผ ๊ฐ๋ฅํ `ArrayBuffer`๋ก ๋ ธ์ถ๋ฉ๋๋ค. ๋ชจ๋ ๋จ์ผ ๊น์ด ๊ฐ์ ์ฝ๊ณ , ํ์ฑํ๊ณ , ๋ถ์ํ ์ ์์ต๋๋ค.
- ์ฃผ์ ์ฌ์ฉ ์ฌ๋ก: ๋ฌผ๋ฆฌ, ์ถฉ๋ ๊ฐ์ง, ์ฅ๋ฉด ๋ถ์. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ํญํ ์ง์ ์ 3D ์ขํ๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ ์ด์บ์คํธ๋ฅผ ์ํํ๊ฑฐ๋, ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํ์ฌ ๊ฐ์ฒด ๋ฐฐ์น๋ฅผ ์ํ ํ ์ด๋ธ์ด๋ ๋ฐ๋ฅ๊ณผ ๊ฐ์ ํํํ ํ๋ฉด์ ์ฐพ์ ์ ์์ต๋๋ค.
- ์ฑ๋ฅ: ์ด ์ต์ ์ ์๋นํ ์ฑ๋ฅ ๋น์ฉ์ ์๋ฐํฉ๋๋ค. ๊น์ด ๋ฐ์ดํฐ๋ CPU๊ฐ ์ ๊ทผํ ์ ์๋๋ก ๊ธฐ๊ธฐ์ ์ผ์/GPU์์ ์์คํ ์ ์ฃผ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ณต์ฌ๋์ด์ผ ํฉ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ์์ ๋งค ํ๋ ์๋ง๋ค ์ด ํฐ ๋ฐ์ดํฐ ๋ฐฐ์ด์ ๋ํด ๋ณต์กํ ๊ณ์ฐ์ ์ํํ๋ฉด ์ฑ๋ฅ ๋ฌธ์ ์ ๋ฎ์ ํ๋ ์ ์๋๋ก ์ฝ๊ฒ ์ด์ด์ง ์ ์์ต๋๋ค. ์ ์คํ๊ณ ์ ์ ํด์ ์ฌ์ฉํด์ผ ํฉ๋๋ค.
๊ถ์ฅ ์ฌํญ: ์คํด๋ฃจ์ ์ ๊ตฌํํ ๊ณํ์ด๋ผ๋ฉด ํญ์ 'gpu-optimized'๋ฅผ ์์ฒญํ์ธ์. `['gpu-optimized', 'cpu-optimized']`์ฒ๋ผ ๋ ๋ค ์์ฒญํ ์๋ ์์ต๋๋ค. ๋ธ๋ผ์ฐ์ ๋ ์ฒซ ๋ฒ์งธ ์ ํธ๋๋ฅผ ์กด์คํ๋ ค๊ณ ์๋ํ ๊ฒ์ ๋๋ค. ์ฝ๋๋ ์์คํ ์ด ์ค์ ๋ก ์ด๋ค ์ฌ์ฉ ๋ชจ๋ธ์ ํ์ฉํ๋์ง ํ์ธํ๊ณ ๋ ๊ฒฝ์ฐ ๋ชจ๋ ์ฒ๋ฆฌํ ์ ์์ ๋งํผ ๊ฒฌ๊ณ ํด์ผ ํฉ๋๋ค.
`dataFormatPreference`: ์ ๋ฐ๋ ๋ ํธํ์ฑ
`dataFormatPreference` ์์ฑ์ ์ํ๋ ๊น์ด ๊ฐ์ ๋ฐ์ดํฐ ํ์๊ณผ ์ ๋ฐ๋์ ๋ํ ํํธ๋ฅผ ์ ๊ณตํ๋ ๋ฌธ์์ด ๋ฐฐ์ด์ ๋๋ค. ์ด ์ ํ์ ์ ํ๋์ ํ๋์จ์ด ํธํ์ฑ ๋ชจ๋์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
'float32'
- ์๋ฏธ: ๊ฐ ๊น์ด ๊ฐ์ ์์ ํ 32๋นํธ ๋ถ๋ ์์์ ์ซ์์ ๋๋ค.
- ์๋ ๋ฐฉ์: ๊ฐ์ด ๋ฏธํฐ ๋จ์์ ๊ฑฐ๋ฆฌ๋ฅผ ์ง์ ๋ํ๋ ๋๋ค. ๋์ฝ๋ฉํ ํ์ ์์ด ๊ทธ๋๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฒํผ์ ๊ฐ์ด 1.5์ด๋ฉด ํด๋น ์ง์ ์ด 1.5๋ฏธํฐ ๋จ์ด์ ธ ์์์ ์๋ฏธํฉ๋๋ค.
- ์ฅ์ : ๋์ ์ ๋ฐ๋์ ์ ฐ์ด๋ ๋ฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ชจ๋์์ ์ฌ์ฉํ๊ธฐ ๋งค์ฐ ์ฝ์ต๋๋ค. ์ ํ๋๋ฅผ ์ํ ์ด์์ ์ธ ํ์์ ๋๋ค.
- ๋จ์ : WebGL 2 ๋ฐ ๋ถ๋ ์์์ ํ ์ค์ฒ๋ฅผ ์ง์ํ๋ ํ๋์จ์ด(์: `OES_texture_float` ํ์ฅ)๊ฐ ํ์ํฉ๋๋ค. ๋ชจ๋ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ, ํนํ ๊ตฌํ ๊ธฐ๊ธฐ์์๋ ์ด ํ์์ ์ฌ์ฉํ์ง ๋ชปํ ์ ์์ต๋๋ค.
'luminance-alpha'
- ์๋ฏธ: WebGL 1 ๋ฐ ๋ถ๋ ์์์ ํ ์ค์ฒ๋ฅผ ์ง์ํ์ง ์๋ ํ๋์จ์ด์์ ํธํ์ฑ์ ์ํด ์ค๊ณ๋ ํ์์ ๋๋ค. ๋ ๊ฐ์ 8๋นํธ ์ฑ๋(ํ๋ ๋ฐ ์ํ)์ ์ฌ์ฉํ์ฌ 16๋นํธ ๊น์ด ๊ฐ์ ์ ์ฅํฉ๋๋ค.
- ์๋ ๋ฐฉ์: ์์ 16๋นํธ ๊น์ด ๊ฐ์ด ๋ ๊ฐ์ 8๋นํธ ๋ถ๋ถ์ผ๋ก ๋๋ฉ๋๋ค. ์ค์ ๊น์ด๋ฅผ ์ป์ผ๋ ค๋ฉด ์ฝ๋์์ ์ด ๋ถ๋ถ๋ค์ ๋ค์ ๊ฒฐํฉํด์ผ ํฉ๋๋ค. ๊ณต์์ ์ผ๋ฐ์ ์ผ๋ก `decodedValue = luminanceValue + alphaValue / 255.0`์ ๋๋ค. ๊ฒฐ๊ณผ๋ 0.0๊ณผ 1.0 ์ฌ์ด์ ์ ๊ทํ๋ ๊ฐ์ด๋ฉฐ, ์ด๋ฅผ ๋ณ๋์ ๊ณ์๋ก ๊ณฑํ์ฌ ๋ฏธํฐ ๋จ์์ ๊ฑฐ๋ฆฌ๋ฅผ ์ป์ด์ผ ํฉ๋๋ค.
- ์ฅ์ : ํจ์ฌ ๋์ ํ๋์จ์ด ํธํ์ฑ. 'float32'๊ฐ ์ง์๋์ง ์์ ๋ ์ ๋ขฐํ ์ ์๋ ๋์ฒด ์๋จ์ ๋๋ค.
- ๋จ์ : ์ ฐ์ด๋๋ ์๋ฐ์คํฌ๋ฆฝํธ์์ ์ถ๊ฐ ๋์ฝ๋ฉ ๋จ๊ณ๊ฐ ํ์ํ์ฌ ์ฝ๊ฐ์ ๋ณต์ก์ฑ์ด ์ถ๊ฐ๋ฉ๋๋ค. ๋ํ 'float32'์ ๋นํด ๋ฎ์ ์ ๋ฐ๋(16๋นํธ)๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ถ์ฅ ์ฌํญ: ๊ฐ์ฅ ์ํ๋ ํ์์ ๋จผ์ ์ง์ ํ์ฌ ๋ ๋ค ์์ฒญํ์ธ์: `['float32', 'luminance-alpha']`. ์ด๋ ๋ธ๋ผ์ฐ์ ์ ๊ณ ์ ๋ฐ๋ ํ์์ ์ ํธํ์ง๋ง, ํ์ํ ๊ฒฝ์ฐ ๋ ํธํ์ฑ ์๋ ํ์๋ ์ฒ๋ฆฌํ ์ ์์์ ์๋ฆฝ๋๋ค. ๋ค์ ๋งํ์ง๋ง, ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ค ํ์์ด ํ์ฉ๋์๋์ง ํ์ธํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํ ์ฌ๋ฐ๋ฅธ ๋ก์ง์ ์ ์ฉํด์ผ ํฉ๋๋ค.
์ค์ฉ์ ๊ตฌํ: ๋จ๊ณ๋ณ ๊ฐ์ด๋
์ด์ ์ด๋ฌํ ๊ฐ๋ ๋ค์ ๊ฒฐํฉํ์ฌ ์ค์ฉ์ ์ธ ๊ตฌํ์ผ๋ก ๋ง๋ค์ด ๋ด ์๋ค. ๊ฐ์ฅ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก์ธ GPU ์ต์ ํ ๊น์ด ๋ฒํผ๋ฅผ ์ฌ์ฉํ ์ฌ์ค์ ์ธ ์คํด๋ฃจ์ ์ ์ด์ ์ ๋ง์ถ ๊ฒ์ ๋๋ค.
1๋จ๊ณ: ๊ฒฌ๊ณ ํ XR ์ธ์ ์์ฒญ ์ค์ ํ๊ธฐ
์ด์์ ์ธ ์ ํธ๋๋ก ์ธ์ ์ ์์ฒญํ๋, ๋์์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์ค๊ณํ ๊ฒ์ ๋๋ค.
let xrSession = null;
let xrDepthInfo = null;
async function onXRButtonClick() {
try {
xrSession = await navigator.xr.requestSession('immersive-ar', {
requiredFeatures: ['local-floor'],
domOverlay: { root: document.body }, // ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์์
depthSensing: {
usagePreference: ['gpu-optimized'],
dataFormatPreference: ['float32', 'luminance-alpha']
}
});
// ... ์ธ์
์์ ๋ก์ง, ์บ๋ฒ์ค, WebGL ์ปจํ
์คํธ ์ค์ ๋ฑ
// ์ธ์
์์ ๋ก์ง์์ ๊น์ด ๊ฐ์ง ๊ตฌ์ฑ์ ๊ฐ์ ธ์ต๋๋ค
const depthSensing = xrSession.depthSensing;
if (depthSensing) {
console.log(`Depth sensing granted with usage: ${depthSensing.usage}`);
console.log(`Depth sensing granted with data format: ${depthSensing.dataFormat}`);
} else {
console.warn("Depth sensing was requested but not granted.");
}
xrSession.requestAnimationFrame(onXRFrame);
} catch (e) {
console.error("Failed to start XR session.", e);
}
}
2๋จ๊ณ: ๋ ๋ ๋ฃจํ์์ ๊น์ด ์ ๋ณด ์ ๊ทผํ๊ธฐ
๋งค ํ๋ ์๋ง๋ค ํธ์ถ๋๋ `onXRFrame` ํจ์ ๋ด์์, ํ์ฌ ๋ทฐ์ ๋ํ ๊น์ด ์ ๋ณด๋ฅผ ๊ฐ์ ธ์์ผ ํฉ๋๋ค.
function onXRFrame(time, frame) {
const session = frame.session;
session.requestAnimationFrame(onXRFrame);
const pose = frame.getViewerPose(xrReferenceSpace);
if (!pose) return;
const glLayer = session.renderState.baseLayer;
const gl = webglContext; // ์ฌ๋ฌ๋ถ์ WebGL ์ปจํ
์คํธ
gl.bindFramebuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
for (const view of pose.views) {
const viewport = glLayer.getViewport(view);
gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
// ์ค์ํ ๋จ๊ณ: ๊น์ด ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
const depthInfo = frame.getDepthInformation(view);
if (depthInfo) {
// ์ด ํ๋ ์๊ณผ ๋ทฐ์ ๋ํ ๊น์ด ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค!
// ์ด๊ฒ์ ๋ ๋๋ง ํจ์์ ์ ๋ฌํฉ๋๋ค
renderScene(view, depthInfo);
} else {
// ์ด ํ๋ ์์๋ ์ฌ์ฉ ๊ฐ๋ฅํ ๊น์ด ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค
renderScene(view, null);
}
}
}
`depthInfo` ๊ฐ์ฒด(`XRDepthInformation`์ ์ธ์คํด์ค)๋ ํ์ํ ๋ชจ๋ ๊ฒ์ ํฌํจํฉ๋๋ค:
- `depthInfo.texture`: ๊น์ด ๋งต์ ํฌํจํ๋ `WebGLTexture` ('gpu-optimized' ์ฌ์ฉ ์).
- `depthInfo.width`, `depthInfo.height`: ๊น์ด ํ ์ค์ฒ์ ํฌ๊ธฐ.
- `depthInfo.normDepthFromNormView`: ์ ๊ทํ๋ ๋ทฐ ์ขํ๋ฅผ ๊น์ด ๋งต ์ํ๋ง์ ์ํ ์ฌ๋ฐ๋ฅธ ํ ์ค์ฒ ์ขํ๋ก ๋ณํํ๋ ๋ฐ ์ฌ์ฉ๋๋ `XRRigidTransform` (ํ๋ ฌ). ์ด๋ ๊น์ด ๋ฐ์ดํฐ๋ฅผ ์ปฌ๋ฌ ์นด๋ฉ๋ผ ์ด๋ฏธ์ง์ ์ ํํ๊ฒ ์ ๋ ฌํ๋ ๋ฐ ํ์์ ์ ๋๋ค.
- `depthInfo.rawValueToMeters`: ์ค์ผ์ผ ํฉํฐ. ํ ์ค์ฒ์ ์์ ๊ฐ์ ์ด ์ซ์๋ฅผ ๊ณฑํ์ฌ ๋ฏธํฐ ๋จ์์ ๊ฑฐ๋ฆฌ๋ฅผ ์ป์ต๋๋ค.
3๋จ๊ณ: GPU ์ต์ ํ ๊น์ด ๋ฒํผ๋ก ์คํด๋ฃจ์ ๊ตฌํํ๊ธฐ
GLSL ์ ฐ์ด๋ ๋ด์์ ๋ง๋ฒ์ด ์ผ์ด๋๋ ๊ณณ์ ๋๋ค. ๋ชฉํ๋ ์ค์ ์ธ๊ณ์ ๊น์ด(ํ ์ค์ฒ์์)๋ฅผ ์ฐ๋ฆฌ๊ฐ ํ์ฌ ๊ทธ๋ฆฌ๊ณ ์๋ ๊ฐ์ ๊ฐ์ฒด์ ๊น์ด์ ๋น๊ตํ๋ ๊ฒ์ ๋๋ค.
์ ์ ์ ฐ์ด๋(Vertex Shader) (๊ฐ์ํ)
์ ์ ์ ฐ์ด๋๋ ๋๋ถ๋ถ ํ์ค์ ์ ๋๋ค. ๊ฐ์ฒด์ ์ ์ ์ ๋ณํํ๊ณ ๊ฒฐ์ ์ ์ผ๋ก ํด๋ฆฝ ๊ณต๊ฐ ์์น๋ฅผ ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋๋ก ์ ๋ฌํฉ๋๋ค.
// GLSL (์ ์ ์
ฐ์ด๋)
attribute vec3 a_position;
uniform mat4 u_projectionMatrix;
uniform mat4 u_modelViewMatrix;
varying vec4 v_clipPosition;
void main() {
vec4 position = u_modelViewMatrix * vec4(a_position, 1.0);
gl_Position = u_projectionMatrix * position;
v_clipPosition = gl_Position;
}
ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋(Fragment Shader) (ํต์ฌ ๋ก์ง)
ํ๋๊ทธ๋จผํธ ์ ฐ์ด๋๊ฐ ํ๋ ์์ ์ ์ํํฉ๋๋ค. ๊น์ด ํ ์ค์ฒ์ ๊ด๋ จ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ๋ํผ(uniform)์ผ๋ก ์ ๋ฌํด์ผ ํฉ๋๋ค.
// GLSL (ํ๋๊ทธ๋จผํธ ์
ฐ์ด๋)
precision mediump float;
varying vec4 v_clipPosition;
uniform sampler2D u_depthTexture;
uniform mat4 u_normDepthFromNormViewMatrix;
uniform float u_rawValueToMeters;
// float32๋ฅผ ์ฌ์ฉํ๋์ง luminance-alpha๋ฅผ ์ฌ์ฉํ๋์ง ์
ฐ์ด๋์ ์๋ ค์ฃผ๋ ์ ๋ํผ
uniform bool u_isFloatTexture;
// ํ์ฌ ํ๋๊ทธ๋จผํธ์ ์ค์ ์ธ๊ณ ๊น์ด๋ฅผ ๋ฏธํฐ ๋จ์๋ก ๊ฐ์ ธ์ค๋ ํจ์
float getDepth(vec2 screenUV) {
// ํ๋ฉด UV์์ ๊น์ด ํ
์ค์ฒ UV๋ก ๋ณํ
vec2 depthUV = (u_normDepthFromNormViewMatrix * vec4(screenUV, 0.0, 1.0)).xy;
// ํ
์ค์ฒ ์ธ๋ถ๋ฅผ ์ํ๋งํ์ง ์๋๋ก ๋ณด์ฅ
if (depthUV.x < 0.0 || depthUV.x > 1.0 || depthUV.y < 0.0 || depthUV.y > 1.0) {
return 10000.0; // ์ธ๋ถ์ธ ๊ฒฝ์ฐ ํฐ ๊ฐ์ ๋ฐํ
}
float rawDepth;
if (u_isFloatTexture) {
rawDepth = texture2D(u_depthTexture, depthUV).r;
} else {
// luminance-alpha ํ์์์ ๋์ฝ๋ฉ
vec2 encodedDepth = texture2D(u_depthTexture, depthUV).ra; // .ra๋ .la์ ๋์ผํฉ๋๋ค
rawDepth = encodedDepth.x + (encodedDepth.y / 255.0);
}
// ์ ํจํ์ง ์์ ๊น์ด ๊ฐ ์ฒ๋ฆฌ (์ข
์ข
0.0)
if (rawDepth == 0.0) {
return 10000.0; // ๋งค์ฐ ๋ฉ๋ฆฌ ์๋ ๊ฒ์ผ๋ก ์ฒ๋ฆฌ
}
return rawDepth * u_rawValueToMeters;
}
void main() {
// ์ด ํ๋๊ทธ๋จผํธ์ ํ๋ฉด ๊ณต๊ฐ UV ์ขํ ๊ณ์ฐ
// v_clipPosition.w๋ ์๊ทผ ๋๋๊ธฐ ์ธ์์
๋๋ค
vec2 screenUV = (v_clipPosition.xy / v_clipPosition.w) * 0.5 + 0.5;
float realWorldDepth = getDepth(screenUV);
// ๊ฐ์ ๊ฐ์ฒด์ ๊น์ด๋ฅผ ๊ฐ์ ธ์ต๋๋ค
// gl_FragCoord.z๋ ํ์ฌ ํ๋๊ทธ๋จผํธ์ ์ ๊ทํ๋ ๊น์ด์
๋๋ค [0, 1]
// ์ด๊ฒ์ ๋ค์ ๋ฏธํฐ๋ก ๋ณํํด์ผ ํฉ๋๋ค (์ด๋ ํฌ์ ํ๋ ฌ์ near/far ํ๋ฉด์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค)
// ์์ฐ์ ์ํ ๊ฐ์ํ๋ ์ ํ ๋ณํ:
float virtualObjectDepth = v_clipPosition.z / v_clipPosition.w;
// ์คํด๋ฃจ์ ๊ฒ์ฌ
if (virtualObjectDepth > realWorldDepth) {
discard; // ์ด ํ๋๊ทธ๋จผํธ๋ ์ค์ ๊ฐ์ฒด ๋ค์ ์์ผ๋ฏ๋ก ๊ทธ๋ฆฌ์ง ์์ต๋๋ค.
}
// ์ฌ๊ธฐ์ ๋๋ฌํ๋ค๋ฉด ๊ฐ์ฒด๊ฐ ๋ณด์ด๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฝ๋๋ค.
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0); // ์์: ๋ง์ ํ ์์
}
๊น์ด ๋ณํ์ ๋ํ ์ค์ ์ฐธ๊ณ ์ฌํญ: `gl_FragCoord.z` ๋๋ ํด๋ฆฝ ๊ณต๊ฐ Z๋ฅผ ๋ฏธํฐ ๋จ์์ ์ ํ ๊ฑฐ๋ฆฌ๋ก ๋ค์ ๋ณํํ๋ ๊ฒ์ ํฌ์ ํ๋ ฌ์ ๋ฐ๋ผ ๋ฌ๋ผ์ง๋ ๊ฐ๋จํ์ง ์์ ์์ ์ ๋๋ค. `float virtualObjectDepth = v_clipPosition.z / v_clipPosition.w;` ๋ผ์ธ์ ๋ทฐ ๊ณต๊ฐ ๊น์ด๋ฅผ ์ ๊ณตํ๋ฉฐ, ์ด๋ ๋น๊ต๋ฅผ ์ํ ์ข์ ์ถ๋ฐ์ ์ ๋๋ค. ์๋ฒฝํ ์ ํ๋๋ฅผ ์ํด์๋ ์นด๋ฉ๋ผ์ near ๋ฐ far ํด๋ฆฌํ ํ๋ฉด์ ํฌํจํ๋ ๊ณต์์ ์ฌ์ฉํ์ฌ ๊น์ด ๋ฒํผ ๊ฐ์ ์ ํํํด์ผ ํฉ๋๋ค.
๋ชจ๋ฒ ์ฌ๋ก ๋ฐ ์ฑ๋ฅ ๊ณ ๋ ค ์ฌํญ
๊ฒฌ๊ณ ํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋ ๊น์ด ์ธ์ ๊ฒฝํ์ ๊ตฌ์ถํ๋ ค๋ฉด ๋ค์ ์ฌํญ์ ์ ์คํ๊ฒ ๊ณ ๋ คํด์ผ ํฉ๋๋ค.
- ์ ์ฐํ๊ณ ๋ฐฉ์ด์ ์ผ๋ก ๊ฐ๋ฐํ๊ธฐ: ์ ํธํ๋ ๊ตฌ์ฑ์ด ํ์ฉ๋ ๊ฒ์ด๋ผ๊ณ ๊ฐ์ ํ์ง ๋ง์ญ์์ค. ํญ์ ํ์ฑ `xrSession.depthSensing` ๊ฐ์ฒด๋ฅผ ์ฟผ๋ฆฌํ์ฌ ํ์ฉ๋ `usage`์ `dataFormat`์ ํ์ธํ์ธ์. ์ง์ํ๋ ค๋ ๋ชจ๋ ๊ฐ๋ฅํ ์กฐํฉ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ๋ ๋๋ง ๋ก์ง์ ์์ฑํ์ญ์์ค.
- ๋ ๋๋ง์๋ GPU ์ฐ์ ์ฌ์ฉํ๊ธฐ: ์ฑ๋ฅ ์ฐจ์ด๋ ์์ฒญ๋ฉ๋๋ค. ๊น์ด๋ ์คํด๋ฃจ์ ์ ์๊ฐํํ๋ ๋ชจ๋ ์์ ์ ๋ํด 'gpu-optimized' ๊ฒฝ๋ก๋ ๋ถ๋๋ฌ์ด 60/90fps ๊ฒฝํ์ ์ํ ์ ์ผํ ์คํ ๊ฐ๋ฅํ ์ต์ ์ ๋๋ค.
- CPU ์์ ์ต์ํ ๋ฐ ์ง์ฐ์ํค๊ธฐ: ๋ฌผ๋ฆฌ๋ ๋ ์ด์บ์คํ ์ ์ํด 'cpu-optimized' ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํด์ผ ํ๋ ๊ฒฝ์ฐ, ๋งค ํ๋ ์๋ง๋ค ์ ์ฒด ๋ฒํผ๋ฅผ ์ฒ๋ฆฌํ์ง ๋ง์ญ์์ค. ๋์ํ๋ ์ฝ๊ธฐ๋ฅผ ์ํํ์ธ์. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์๊ฐ ํ๋ฉด์ ํญํ๋ฉด ํด๋น ํน์ ์ขํ์ ๊น์ด ๊ฐ๋ง ์ฝ์ผ์ญ์์ค. ๋ฉ์ธ ์ค๋ ๋์์ ๋ฌด๊ฑฐ์ด ๋ถ์ ์์ ์ ์คํ๋ก๋ํ๊ธฐ ์ํด ์น ์์ปค(Web Worker) ์ฌ์ฉ์ ๊ณ ๋ คํ์ธ์.
- ๋๋ฝ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์์ ์ผ๋ก ์ฒ๋ฆฌํ๊ธฐ: ๊น์ด ์ผ์๋ ์๋ฒฝํ์ง ์์ต๋๋ค. ๊ฒฐ๊ณผ์ ์ธ ๊น์ด ๋งต์๋ ํนํ ๋ฐ์ฌ๋๊ฑฐ๋ ํฌ๋ช ํ ํ๋ฉด์์ ๊ตฌ๋ฉ, ๋ ธ์ด์ฆ๊ฐ ์๋ ๋ฐ์ดํฐ, ๋ถ์ ํ์ฑ์ด ์์ ๊ฒ์ ๋๋ค. ์คํด๋ฃจ์ ์ ฐ์ด๋์ ๋ฌผ๋ฆฌ ๋ก์ง์ ์๊ฐ์ ๊ฒฐํจ์ด๋ ์๋ชป๋ ๋์์ ํผํ๊ธฐ ์ํด ์ ํจํ์ง ์์ ๊น์ด ๊ฐ(์ข ์ข 0์ผ๋ก ํ์๋จ)์ ์ฒ๋ฆฌํด์ผ ํฉ๋๋ค.
- ์ขํ๊ณ ๋ง์คํฐํ๊ธฐ: ์ด๊ฒ์ ๊ฐ๋ฐ์๋ค์ด ํํ ์คํจํ๋ ์ง์ ์ ๋๋ค. ๋ทฐ, ํด๋ฆฝ, ์ ๊ทํ๋ ์ฅ์น, ํ ์ค์ฒ ๋ฑ ๋ค์ํ ์ขํ๊ณ์ ์ธ์ฌํ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ด๊ณ `normDepthFromNormView`์ ๊ฐ์ ์ ๊ณต๋ ํ๋ ฌ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฌ์ฉํ์ฌ ๋ชจ๋ ๊ฒ์ ์ ๋ ฌํด์ผ ํฉ๋๋ค.
- ์ ๋ ฅ ์๋น ๊ด๋ฆฌํ๊ธฐ: ๊น์ด ๊ฐ์ง ํ๋์จ์ด, ํนํ LiDAR์ ๊ฐ์ ๋ฅ๋ ์ผ์๋ ์๋นํ ๋ฐฐํฐ๋ฆฌ ์ ๋ ฅ์ ์๋นํ ์ ์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ง์ ์ผ๋ก ํ์ํ ๋๋ง 'depth-sensing' ๊ธฐ๋ฅ์ ์์ฒญํ์ธ์. ์ฌ์ฉ์๊ฐ ์ ๊ทน์ ์ผ๋ก ์ฐธ์ฌํ์ง ์์ ๋ ์ ๋ ฅ์ ์ ์ฝํ๊ธฐ ์ํด XR ์ธ์ ์ด ์ ๋๋ก ์ผ์ ์ค๋จ๋๊ณ ์ข ๋ฃ๋๋์ง ํ์ธํ์ญ์์ค.
WebXR ๊น์ด ๊ฐ์ง์ ๋ฏธ๋
๊น์ด ๊ฐ์ง๋ ๊ธฐ์ด ๊ธฐ์ ์ด๋ฉฐ WebXR ์ฌ์์ ์ด๋ฅผ ์ค์ฌ์ผ๋ก ๊ณ์ ๋ฐ์ ํ๊ณ ์์ต๋๋ค. ๊ธ๋ก๋ฒ ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ๋ ๋ฏธ๋์ ๋์ฑ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ๊ธฐ๋ํ ์ ์์ต๋๋ค:
- ์ฅ๋ฉด ์ดํด ๋ฐ ๋ฉ์ํ(Meshing): ๋ค์ ๋ ผ๋ฆฌ์ ๋จ๊ณ๋ XRMesh ๋ชจ๋๋ก, ๊น์ด ๋ฐ์ดํฐ๋ก๋ถํฐ ๊ตฌ์ถ๋ ์ค์ 3D ์ผ๊ฐํ ๋ฉ์๋ฅผ ์ ๊ณตํ ๊ฒ์ ๋๋ค. ์ด๋ ํจ์ฌ ๋ ํ์ค์ ์ธ ๋ฌผ๋ฆฌ, ๋ด๋น๊ฒ์ด์ ๋ฐ ์กฐ๋ช ์ ๊ฐ๋ฅํ๊ฒ ํ ๊ฒ์ ๋๋ค.
- ์๋ฏธ๋ก ์ ๋ ์ด๋ธ(Semantic Labels): ํ๋ฉด์ ๊ธฐํํ์ ๊ตฌ์กฐ๋ฟ๋ง ์๋๋ผ ๊ทธ๊ฒ์ด '๋ฐ๋ฅ', '๋ฒฝ' ๋๋ 'ํ ์ด๋ธ'์ด๋ผ๋ ๊ฒ์ ์๋ ๊ฒ์ ์์ํด๋ณด์ธ์. ๋ฏธ๋์ API๋ ์ด ์๋ฏธ๋ก ์ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ฌ ๋๋๋๋ก ์ง๋ฅ์ ์ด๊ณ ์ํฉ ์ธ์์ ์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฅํ๊ฒ ํ ๊ฒ์ ๋๋ค.
- ํฅ์๋ ํ๋์จ์ด ํตํฉ: AR ์๊ฒฝ๊ณผ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ๊ฐ ๋ ๋์ ์ผ์์ ํ๋ก์ธ์๋ก ๋์ฑ ๊ฐ๋ ฅํด์ง์ ๋ฐ๋ผ WebXR์ ์ ๊ณต๋๋ ๊น์ด ๋ฐ์ดํฐ์ ํ์ง, ํด์๋ ๋ฐ ์ ํ๋๊ฐ ๊ทน์ ์ผ๋ก ํฅ์๋์ด ์๋ก์ด ์ฐฝ์์ ๊ฐ๋ฅ์ฑ์ ์ด์ด์ค ๊ฒ์ ๋๋ค.
๊ฒฐ๋ก
WebXR ๊น์ด ๊ฐ์ง API๋ ๊ฐ๋ฐ์๊ฐ ์๋ก์ด ์ฐจ์์ ์น ๊ธฐ๋ฐ ์ฆ๊ฐ ํ์ค ๊ฒฝํ์ ๋ง๋ค ์ ์๋๋ก ์ง์ํ๋ ํ์ ์ ์ธ ๊ธฐ์ ์ ๋๋ค. ๋จ์ํ ๊ฐ์ฒด ๋ฐฐ์น๋ฅผ ๋์ด ํ๊ฒฝ ์ดํด๋ฅผ ์์ฉํจ์ผ๋ก์จ, ์ฐ๋ฆฌ๋ ๋ ํ์ค์ ์ด๊ณ ์ํธ์์ฉ์ ์ด๋ฉฐ ์ฌ์ฉ์์ ์ธ๊ณ์ ์ง์ ์ผ๋ก ํตํฉ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํ ์ ์์ต๋๋ค. ๊น์ด ๋ฒํผ์ ๊ตฌ์ฑ์ ๋ง์คํฐํ๋ ๊ฒโ์ฆ, 'cpu-optimized'์ 'gpu-optimized' ์ฌ์ฉ, ๊ทธ๋ฆฌ๊ณ 'float32'์ 'luminance-alpha' ๋ฐ์ดํฐ ํ์ ๊ฐ์ ์ฅ๋จ์ ์ ์ดํดํ๋ ๊ฒโ์ด ์ ์ฌ๋ ฅ์ ๋ฐํํ๋ ๋ฐ ํ์ํ ํต์ฌ ๊ธฐ์ ์ ๋๋ค.
์ฌ์ฉ์์ ๊ธฐ๊ธฐ ๊ธฐ๋ฅ์ ์ ์ํ ์ ์๋ ์ ์ฐํ๊ณ ์ฑ๋ฅ์ด ๋ฐ์ด๋๋ฉฐ ๊ฒฌ๊ณ ํ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์ถํจ์ผ๋ก์จ, ์ฌ๋ฌ๋ถ์ ๋จ์ผ ๊ฒฝํ์ ๋ง๋๋ ๊ฒ์ ๋์ด ๋ชฐ์ ํ ๊ณต๊ฐ ์น์ ๊ธฐ์ด์ ๊ธฐ์ฌํ๊ณ ์๋ ๊ฒ์ ๋๋ค. ๋๊ตฌ๋ ์ฌ๋ฌ๋ถ์ ์์ ์์ต๋๋ค. ์ด์ ๊น์ด ํ๊ณ ๋ค์ด ๋ฏธ๋๋ฅผ ๊ฑด์คํ ์๊ฐ์ ๋๋ค.