ã¬ã³ããªã³ã°ã¨ WebXR ãã¬ã¼ã ã¢ãã¡ã¼ã·ã§ã³ã³ã¼ã«ããã¯
WebXR ç°å¢ãã»ããã¢ããããé²è¡ä¸ã® XR ç°å¢ã»ãã·ã§ã³ã表ã XRSession ã使ããããã¬ã³ããªã³ã°ã®ããã«ã·ã¼ã³ã®ãã¬ã¼ã ã XR æ©å¨ã«æä¾ããå¿
è¦ãããã¾ãã ãã®è¨äºã§ã¯ãXRSession ã使ç¨ãã¦åãã¬ã¼ã ã表ã XRFrame ãªãã¸ã§ã¯ããåå¾ããããã使ç¨ãã¦ãXR æ©å¨ã«é
ä¿¡ããããã®ãã¬ã¼ã ãããã¡ã¼ãæºåããã¬ã³ããªã³ã°ã«ã¼ãã§ XR ã·ã¼ã³ã®ãã¬ã¼ã ãæ©å¨ã«é§åããããã»ã¹ã«ã¤ãã¦èª¬æãã¾ãã
ä»®æ³ç°å¢ãã¬ã³ããªã³ã°ããåã«ãnavigator.xr.requestSession() ã¡ã½ããã使ç¨ã㦠XRSession ã使ãããã¨ã«ãããWebXR ã»ãã·ã§ã³ã確ç«ããå¿
è¦ãããã¾ãã ã¾ããã»ãã·ã§ã³ããã¬ã¼ã ãããã¡ã¼ã«é¢é£ä»ãã¦ãä»ã®ã»ããã¢ããã¿ã¹ã¯ãå®è¡ããå¿
è¦ãããã¾ãã ãããã®ã»ããã¢ããã¿ã¹ã¯ã«ã¤ãã¦ã¯ãWebXR ã»ãã·ã§ã³ã®èµ·åã¨åæ¢ã®è¨äºã§èª¬æããã¦ãã¾ãã
ã¬ã³ãã©ã¼ã®æºå
XR ã»ãã·ã§ã³ãã»ããã¢ããããWebGL ãã¬ã¼ã ãããã¡ã¼ãæ¥ç¶ããWebGL ãã·ã¼ã³ãã¬ã³ããªã³ã°ããããã«å¿
è¦ãªãã¼ã¿ã§æºåããããã¬ã³ãã©ã¼ãã»ããã¢ãããã¦å®è¡ãéå§ã§ãã¾ãã ããã¯ãæç»ããåç
§ç©ºéãåå¾ãããã¨ããå§ã¾ãã¾ãã ãã®åç¹ã¨æ¹åã¯ããã¥ã¼ã¢ã¼ã®éå§ä½ç½®ã¨è¦ç·æ¹åã«è¨å®ãã¾ãã ãããæã«å
¥ã£ãããæ¬¡ã«ã·ã¼ã³ãã¬ã³ããªã³ã°ããããã«ãã¬ã¼ã ãããã¡ã¼ãå¿
è¦ã«ãªã£ãã¨ãã«ãã©ã¦ã¶ã¼ãããªãã®ã¬ã³ããªã³ã°é¢æ°ãå¼ã³åºãããã«è¦æ±ãã¾ãã ããã¯ãXRSession ã¡ã½ããã® requestAnimationFrame() ãå¼ã³åºããã¨ã«ãã£ã¦è¡ãã¾ãã
ãããã£ã¦ãã¬ã³ãã©ã¼ã®æã¯ããã¯æ¬¡ã®ããã«ãªãã¾ãã
let worldRefSpace;
async function runXR(xrSession) {
worldRefSpace = await xrSession.requestReferenceSpace("local");
if (worldRefSpace) {
viewerRefSpace = worldRefSpace.getOffsetReferenceSpace(
new XRRigidTransform(viewerStartPosition, viewerStartOrientation),
);
animationFrameRequestID = xrSession.requestAnimationFrame(myDrawFrame);
}
}
没å
¥åä¸çã®åç
§ç©ºéãåå¾ããå¾ãããã¯ããã®ä½ç½®ã¨æ¹åã表ã XRRigidTransform ã使ããXRReferenceSpace ã®ã¡ã½ãã getOffsetReferenceSpace() ãå¼ã³åºããã¨ã«ããããã¥ã¼ã¢ã¼ã®ä½ç½®ã¨æ¹åã表ããªãã»ããåç
§ç©ºéã使ãã¾ãã
次ã«ãXRSession ã®ã¡ã½ãã requestAnimationFrame() ãå¼ã³åºãã¦æåã®ã¢ãã¡ã¼ã·ã§ã³ãã¬ã¼ã ãã¹ã±ã¸ã¥ã¼ã«ãããã¬ã¼ã ãã¬ã³ããªã³ã°ããããã®ã³ã¼ã«ããã¯é¢æ° myDrawFrame() ãæä¾ãã¾ãã
ãã®ã³ã¼ãã«ã¯ã«ã¼ãããªããã¨ã«æ³¨æãã¦ãã ããï¼ ä»£ããã«ããã¬ã¼ã ã¬ã³ããªã³ã°ã³ã¼ãï¼ãã®å ´å㯠myDrawFrame() ã¨ãã颿°ï¼ããããä¸åº¦ requestAnimationFrame() ãå¼ã³åºãã¦å¥ã®ãã¬ã¼ã ãæç»ããæå»ãã¹ã±ã¸ã¥ã¼ã«ãã¾ãã
ãªãã¬ãã·ã¥ã¬ã¼ãã¨ãã¬ã¼ã ã¬ã¼ã
ç»é¢ãæå¾ã«ãªãã¬ãã·ã¥ããã¦ãã XRSession ã®ã¡ã½ãã requestAnimationFrame() ãå¼ã³åºããã¨ããã¨ããã©ã¦ã¶ã¼ã¯ãã¢ããªã¾ãã¯ãµã¤ãã¦ã£ã³ãã¦ãåæç»ããæºåãã§ãããã³ã«ãã¬ã¼ã ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ãå¼ã³åºãã¾ãã ãã®ã³ã³ããã¹ãã§ã¯ããåæç»ãã¨ã¯ãç»é¢ã«è¡¨ç¤ºãããã³ã³ãã³ãããDOM ããã³ãã®ä¸ã®è¦ç´ ãç¾æç¹ã§æç¤ºãããã¨ãã¦ãããã®ã¨ä¸è´ãããã¨ãä¿è¨¼ããããã»ã¹ãæå³ãã¾ãã
ãã¼ãã¦ã§ã¢åç´ãªãã¬ãã·ã¥ã¬ã¼ã
ãã©ã¦ã¶ã¼ã¯ãWebXR ã³ã³ãã³ãã表示ããã¦ãã <canvas> ããªãã¬ãã·ã¥ããæºåãã§ããã¨ããã¬ã¼ã ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ãå¼ã³åºãã¾ãã ãã®ã³ã¼ã«ããã¯ã¯ãæå®ãããã¿ã¤ã ã¹ã¿ã³ãã¨ãã¢ãã«ããã¯ã¹ãã£ã¼ãªã©ã®ä»ã®é¢é£ãã¼ã¿ãããã³ã¢ããªã±ã¼ã·ã§ã³ã®ç¶æ
ã使ç¨ãã¦ãæå®ãããæå»ã«è¡¨ç¤ºãããããã«ãã·ã¼ã³ã WebGL ããã¯ãããã¡ã¼ã«ã¬ã³ããªã³ã°ãã¾ãã ã³ã¼ã«ããã¯ãæ»ãã¨ããã©ã¦ã¶ã¼ã¯æå¾ã«ç»é¢ããªãã¬ãã·ã¥ããã¦ãã夿´ããããã®ã¨å
±ã«ããã®ããã¯ãããã¡ã¼ããã£ã¹ãã¬ã¤ã¾ã㯠XR æ©å¨ã«è»¢éãã¾ãã
æ´å²çã«ããã£ã¹ãã¬ã¤ã¯æ¯ç§ 60 åãªãã¬ãã·ã¥ããã¦ãã¾ãã ããã¯ãã¿ã¤ãã³ã°ãåãããããã«ãç±³å½ã§ã¯ 1 ç§ããã 60 åï¼ã¨ã¼ãããã§ã¯ 50 åï¼å¾ªç°ãã AC é é»ç¶²ã®é»æµããã¼æ³¢å½¢ã使ç¨ããåæã®ãã£ã¹ãã¬ã¤ã«ãããã®ã§ãã æ¬¡ã®ããã«ããã®ãã¨ã¯ããã¤ãã®ç°ãªãååã§ç¤ºããã¦ãã¾ããããããã¯ãã¹ã¦åçã¾ãã¯ã»ã¼åãã§ãã
- ãªãã¬ãã·ã¥ã¬ã¼ãï¼Refresh rateï¼
- åç´ãªãã¬ãã·ã¥ã¬ã¼ãï¼Vertical refresh rateï¼
- åç´å¸°ç·æ¶å»ã¬ã¼ãï¼Vertical blanking rateãVBLï¼
- åç´åæã¬ã¼ãï¼Vertical sync rateï¼
ä»ã«ãåæ§ã®ç¨èªã使ç¨ããã¦ãã¾ããããããä½ã¨å¼ã°ãããã«é¢ä¿ãªããé©ç¨ãããæ¸¬å®åä½ã¯ãã«ãï¼Hzï¼ã§ãã 1 ç§ããã 60 åãªãã¬ãã·ã¥ãããã£ã¹ãã¬ã¤ã«ã¯ã60 Hz ã®ãªãã¬ãã·ã¥ã¬ã¼ããããã¾ãã ã¤ã¾ãã1 ç§éã«è¡¨ç¤ºã§ãããã¬ã¼ã ã®æå¤§æ°ã¯ 60 ã§ãã ãããè¶ ãã 1 ç§ãããã®ãã¬ã¼ã æ°ã«é¢ä¿ãªãã1 ç§ã®éã« 60 ãã¬ã¼ã ããç»é¢ã«è¡¨ç¤ºããã¾ããã
ãã ãããã¹ã¦ã®ãã£ã¹ãã¬ã¤ã 60 Hz ã§åä½ããããã§ã¯ããã¾ããã æè¿ã§ã¯ããã髿§è½ã®ãã£ã¹ãã¬ã¤ãã¯ããã«é«ããªãã¬ãã·ã¥ã¬ã¼ãã使ç¨ãå§ãã¦ãã¾ãã ä¾ãã°ã120 Hzãã¤ã¾ã 120 ãã¬ã¼ã /ç§ã®ãã£ã¹ãã¬ã¤ã¯ãã¾ãã¾ãä¸è¬çã«ãªã£ã¦ãã¾ãã ãã©ã¦ã¶ã¼ã¯å¸¸ã«ãã£ã¹ãã¬ã¤ã¨åãã¬ã¼ãã§ãªãã¬ãã·ã¥ã試ã¿ã¾ãã ã¤ã¾ããä¸é¨ã®ã³ã³ãã¥ã¼ã¿ã¼ã§ã¯ãã³ã¼ã«ããã¯ã¯ 1 ç§ãããæå¤§ 60 åå®è¡ããã¾ãããä»ã®ã³ã³ãã¥ã¼ã¿ã¼ã§ã¯ããã¬ã¼ã ã¬ã¼ãã«ãã£ã¦ç°ãªã 1 ç§ããã 90 ã¾ã㯠120 åããããã¯ãã以ä¸å¼ã³åºãããå ´åãããã¾ãã
åãã¬ã¼ã ã®ã¬ã³ããªã³ã°ã«å©ç¨ã§ããæé
ããã«ããããã¬ã¼ã éã§å©ç¨å¯è½ãªã»ã¨ãã©ã®æéã使ç¨ãããã¨ãéè¦ã«ãªãã¾ãã ã¦ã¼ã¶ã¼ã®ç«¯æ«ã 60 Hz ã®ãã£ã¹ãã¬ã¤ã使ç¨ãã¦ããå ´åãã³ã¼ã«ããã¯ã¯ 1 ç§ãããæå¤§ 60 åå¼ã³åºããããããããé »ç¹ã«å¼ã³åºããããã¨ã¯ãªãã®ã§ã確å®ã«ã§ãããã¨ããããã¨ãç®æ¨ã§ãã ãããå®ç¾ããã«ã¯ãã¡ã¤ã³ã¹ã¬ããå¤ã§å¯è½ãªéãå®è¡ãããã¬ã¼ã ã¬ã³ããªã³ã°ã®ã³ã¼ã«ããã¯ãã§ããã ãå¹ççã«ãã¾ãã 以ä¸ã®å³ã¯ãæéã® 60 Hz ãããã¯ã¸ã®åå²ã示ãã¦ãã¾ãã åãããã¯ã¯ãå°ãªãã¨ãé¨åçã«ã·ã¼ã³ã®ã¬ã³ããªã³ã°ã«ä½¿ç¨ããã¦ãã¾ãã
ã³ã³ãã¥ã¼ã¿ã®ãã¸ã¼ç¶æ ãå¢ãã«ã¤ãã¦ãã³ã¼ã«ããã¯ããã¬ã¼ã ãã¨ã«æ£ç¢ºã«å¼ã³åºããã¨ãã§ããªããªãããã¬ã¼ã ãã¹ãããããªããã°ãªããªãå ´åããããããããã¯éè¦ã§ãã ãããã³ãè½ã¡ï¼dropping framesï¼ã¨å¼ã³ã¾ãã ããã¯ãã¬ã³ããªã³ã°ãé å»¶ãããããã¾ãã¯ã¬ã³ããªã³ã°èªä½ã«ä½¿ç¨å¯è½ãªæéãããé·ãæéãããã£ãããã«ããã¬ã¼ã ã®ã¬ã³ããªã³ã°ã«ãããæéããã¬ã¼ã éã§ä½¿ç¨å¯è½ãªæéãè¶ ããã¨çºçãã¾ãã
ä¸ã®å³ã§ã¯ããã¬ã¼ã 3 ããã¤ã³ããããäºå®ã«ãªãã¾ã§ãã¬ã¼ã 2 ãã¬ã³ããªã³ã°ãå®äºããªãã£ãããããã¬ã¼ã 3 ã¯ã³ãè½ã¡ãã¦ãã¾ãã æ¬¡ã«æç»ããããã¬ã¼ã ã¯ãã¬ã¼ã 4 ã«ãªãã¾ãã ããã¯ãã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ã«æ¸¡ãããã¿ã¤ã ã¹ã¿ã³ããå½¹ç«ã¤ãã 1 ã¤ã®çç±ã§ãã ãã¬ã¼ã çªå·ã§ã¯ãªãæéã«åºã¥ãã¦ã·ã¼ã³ãæ§æãããã¨ã«ãããã¬ã³ããªã³ã°ããããã¬ã¼ã ãé ãããã¨ãªããæå¾ ãããã®ã¨ä¸è´ãããã¨ãä¿è¨¼ã§ãã¾ãã
ãã¬ã¼ã ãã³ãè½ã¡ããã¨ãå½±é¿ãåãã表示é åã®ã³ã³ãã³ãã¯ããã¬ã¼ã ã«ã¼ããééãã¦ã夿´ããã¾ããã ãã®ãããã¨ãã©ããã¬ã¼ã ãã³ãè½ã¡ãããã¨ã¯é常ãã¾ãç®ç«ã¡ã¾ããããé »ç¹ã«çºçãå§ããå ´åï¼ç¹ã«ãé常ã«çãæéã«è¤æ°ã®ãã¬ã¼ã ãã³ãè½ã¡ããå ´åï¼ã¯ãä¸å¿«ã«ãªãããã£ã¹ãã¬ã¤ã使ç¨ã§ããªããªãå¯è½æ§ãããã¾ãã
幸ãããã¬ã¼ã éã§ä½¿ç¨ã§ããæéã 1/refreshRate ç§ã¨ãã¦ç°¡åã«è¨ç®ã§ãã¾ãã ã¤ã¾ãã1 ããã£ã¹ãã¬ã¤ã®ãªãã¬ãã·ã¥ã¬ã¼ãã§é¤ç®ãã¾ãã çµæã®å¤ã¯ããã¬ã¼ã ãã³ãè½ã¡ããªãããã«ããããã«ãåãã¬ã¼ã ãã¬ã³ããªã³ã°ããã®ã«ä½¿ç¨ã§ããæéã§ãã ä¾ãã°ã60 Hz ã®ãã£ã¹ãã¬ã¤ã§ã¯ã1 ãã¬ã¼ã ã®ã¬ã³ããªã³ã°ã« 1/60 ç§ãã¤ã¾ã 0.0166667 ç§ã使ç¨ããã¾ãã ã¾ããããã¤ã¹ã®ãªãã¬ãã·ã¥ã¬ã¼ãã 120 Hz ã®å ´åãã³ãè½ã¡ãé¿ãããå ´åãåãã¬ã¼ã ãã¬ã³ããªã³ã°ããã®ã«å¿
è¦ãªæé㯠0.00883333 ç§ããããã¾ããã
ãã ãããã¼ãã¦ã§ã¢ãå®éã«ã¯ 120 Hz ã§ããå ´åã§ããæ¯ç§ 60 åãªãã¬ãã·ã¥ããã ãã§ååã§ãããé常ã¯ãããã¿ã¼ã²ããã¨ãããã¨ããå§ããã¾ãã 60 FPS ã¯ãã§ã«ãã»ã¨ãã©ã®äººãã¢ãã¡ã¼ã·ã§ã³ãåãªãé«éã®ä¸é£ã®éæ¢ç»åã§ã¯ãªããã¨ãç°¡åã«æ¤åºã§ãããã¤ã³ããè¶ ãã¦ãã¾ãã ã¤ã¾ããå¤å¥ãã¤ããªãã¨ãã¯ããã£ã¹ãã¬ã¤ã 60 Hz ã§ãªãã¬ãã·ã¥ããã¦ããã¨æ³å®ã§ãã¾ãã ã³ã¼ããé©åã«è¨è¿°ããã¦ããéãããã¹ã¦ãåé¡ãªãåä½ãã¾ãã
ã¬ã³ãã©ã¼ã®ããã©ã¼ãã³ã¹ã®åé¡
æããã«ããã¬ã¼ã ãã¨ã«ã·ã¼ã³ãã¬ã³ããªã³ã°ããæéã¯ã»ã¨ãã©ããã¾ããã ããã ãã§ãªããã¬ã³ãã©ã¼èªä½ããã®æéãããé·ãå®è¡ãããã¨ããã¬ã¼ã ãã³ãè½ã¡ããã ãã§ãªãããã®æéãå®å ¨ã«ç¡é§ã«ãªããä»ã®ã³ã¼ãããã®ãã¬ã¼ã ã«å¯¾ãã¦ã¾ã£ããå®è¡ãããªããªãå¯è½æ§ãããã¾ãã
ããã ãã§ãªããã¬ã³ããªã³ã°ãåç´ãªãã¬ãã·ã¥å¢çãã¾ããå ´åããã£ã¢ãªã³ã°å¹æï¼tearing effectï¼ãçºçããå¯è½æ§ãããã¾ãã ãã£ã¢ãªã³ã°ã¯ãåã®ãã¬ã¼ã ãã¾ã ç»é¢ã«æç»ããã¦ããéã«ãã£ã¹ãã¬ã¤ãã¼ãã¦ã§ã¢ã次ã®ãªãã¬ãã·ã¥ãµã¤ã¯ã«ãéå§ããã¨çºçãã¾ãã ãã®çµæãç»é¢ã®ä¸é¨ã«æ°ãããã¬ã¼ã ã表示ããã¾ããããã¬ã¼ã ã®ä¸é¨ã«ã¯ãåã®ãã¬ã¼ã ã¨å ´åã«ãã£ã¦ã¯ãã®åã®ãã¬ã¼ã ã®çµã¿åããã表示ãããè¦è¦å¹æã¨ãªãã¾ãã
ãããã£ã¦ãããªãã®ä½¿å½ã¯ãå©ç¨å¯è½ãªæéãè¶ éããããã³ãè½ã¡ãã¡ã¤ã³ã¹ã¬ããã®éåº¦ã®æªç¨ãå¼ãèµ·ããããããªãããã«ãã³ã¼ããååã«ã¿ã¤ããã¤è»½éã«ä¿ã¤ãã¨ã§ãã
ãããã®çç±ã«ãããã¬ã³ãã©ã¼ãããªãå°ããã¦è»½éã§ãã»ã¨ãã©ä½ããããã¨ããªãã®ã§ãªãéãããã©ã¦ã¶ã¼ãä»ã®å¦çãè¡ãéã«æ¬¡ã®ãã¬ã¼ã ãè¨ç®ã§ããããã«ãã§ããéããã¹ã¦ãã¯ã¼ã«ã¼ã«ãªããã¼ããããã¨ãæ¤è¨ããå¿ è¦ãããã¾ãã ãã¬ã¼ã ãå®éã«å¼ã³åºãããåã«è¨ç®ã¨ãã¼ã¿ãæºåããã ãã§ããµã¤ãã¾ãã¯ã¢ããªãããå¹ççã«ã¬ã³ããªã³ã°ããã¡ã¤ã³ã¹ã¬ããã®ããã©ã¼ãã³ã¹ãåä¸ãããä¸è¬çã«ã¦ã¼ã¶ã¼ã¨ã¯ã¹ããªã¨ã³ã¹ãåä¸ããããã¨ãã§ãã¾ãã
幸ããã¬ã³ããªã³ã°ã®ãã¼ãºãç¹ã«éãå ´åã¯ãå½±é¿ãããã«æ¸ãããããã©ã¼ãã³ã¹ãæé©åããããã«ä½¿ç¨ã§ããããã¤ãã®ããªãã¯ãããã¾ãã WebXR ããã©ã¼ãã³ã¹ã¬ã¤ããåç §ãã¦ãããã©ã¼ãã³ã¹ãã§ããéãåä¸ãããããã®æ¨å¥¨äºé ã¨ãã³ãã確èªãã¦ãã ããã
WebXR ãã¬ã¼ã
ãã¬ã¼ã ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯é¢æ°ã¯ã2 ã¤ã®ãã©ã¡ã¼ã¿ã¼ãå
¥åã¨ãã¦åãåãã¾ãã ãã¬ã¼ã ã対å¿ããæå»ã¨ããã®æå»ã®ã·ã¼ã³ã®ç¶æ
ãè¨è¿°ãã XRFrame ãªãã¸ã§ã¯ãã§ãã
3D ã®å å¦
ç§ãã¡ã 2 ã¤ã®ç®ãæã¤ã«ã¯çç±ãããã¾ãã 2 ã¤ã®ç®ãæã¤ãã¨ã§ããããããæ¬è³ªçã«ãããã«ç°ãªãè§åº¦ããä¸çãè¦ããã¨ãã§ãã¾ãã ãããã¯æ¢ç¥ã®åºå®è·é¢ã ãé¢ãã¦ãããããç§ãã¡ã®è³ã¯åºæ¬çãªå¹¾ä½å¦ã¨ä¸è§æ³ãå®è¡ãããã®æ å ±ãã 3D ã®å®å¨ã®æ¬è³ªãçè§£ã§ãã¾ãã ã¾ããé è¿æ³ï¼perspectiveï¼ã大ããã®éããããã«ã¯é常ã3 çªç®ã®æ¬¡å ã®è©³ç´°ãçè§£ããããã«ç©äºãã©ã®ããã«è¦ãããã«ã¤ãã¦ã®çè§£ãå©ç¨ãã¾ãã ãããã®è¦å ã¯ãã¨ããããç§ãã¡ã®å¥¥è¡ãç¥è¦ï¼depth perceptionï¼ã®æºã§ãã
ã°ã©ãã£ãã¯ã¹ãã¬ã³ããªã³ã°ããã¨ãã« 3 次å ã®å¹»æ³ã使ããã«ã¯ããããã®è¦å ãã§ããã ãå¤ãã·ãã¥ã¬ã¼ãããå¿ è¦ãããã¾ãã ããããã·ãã¥ã¬ã¼ãããã»ã©ãããã¦æ£ç¢ºã«è¡ãã»ã©ã人éã®è³ãã ã¾ã㦠3D ã§ç»åãç¥è¦ããããã¨ãã§ãã¾ãã XR ã®å©ç¹ã¯ãå¤å ¸çãªåç¼ãã¯ããã¯ã使ç¨ã㦠3D ã°ã©ãã£ãã¯ã¹ï¼é è¿æ³ã大ãããã·ãã¥ã¬ã¼ããããè¦å·®ï¼ãã·ãã¥ã¬ã¼ãã§ããã ãã§ãªããã¢ãã¡ã¼ã·ã§ã³ã®ãã¬ã¼ã ãã¨ã«ãåç®ã«ã¤ã 1 åãã¤ã·ã¼ã³ã 2 åã¬ã³ããªã³ã°ãããã¨ã§ã両ç¼è¦ï¼ã¤ã¾ãã2 ã¤ã®ç®ã使ç¨ããè¦è¦ï¼ãã·ãã¥ã¬ã¼ãã§ãããã¨ã§ãã
å
¸åçãªäººéã®ç³åéè·é¢ï¼pupillary distanceãç³åã®ä¸å¿éã®è·é¢ï¼ã¯ã54 ã 74 ããªã¡ã¼ãã«ï¼0.054 ã 0.074 ã¡ã¼ãã«ï¼ã§ãã ãããã£ã¦ããã¥ã¼ã¢ã¼ã®é ã®ä¸å¿ã [0.0, 2.0, 0.0]ï¼æ°´å¹³æ¹åã®ç©ºéã®ä¸å¿ã§å°ä¸ã¬ãã«ã®ç´ 2 ã¡ã¼ãã«ï¼ã«ããå ´åãã¾ã [-0.032, 2.0, 0.0]ï¼ä¸å¿ãã左㫠32 mmï¼ããã·ã¼ã³ãã¬ã³ããªã³ã°ããæ¬¡ã« [0.032, 2.0, 0.0]ï¼ä¸å¿ããå³ã« 32 mmï¼ã§åã³ã¬ã³ããªã³ã°ããå¿
è¦ãããã¾ãã ãã®ããã«ãã¦ããã¥ã¼ã¢ã¼ã®ç®ã®ä½ç½®ã人éã®å¹³åç³åè·é¢ 64 mm ã«é
ç½®ãã¾ãã
ãã®è·é¢ï¼ã¾ã㯠XR ã·ã¹ãã ã使ç¨ããããã«æ§æããã¦ããç³åéè·é¢ï¼ã¯ãç¶²èæªè¦ï¼åç¶²èã®è¦ãæ¹ã®éãï¼ã¨è¦å·®å¹æã«ãã£ã¦è³ããªãã¸ã§ã¯ãã¾ã§ã®è·é¢ã¨ãªãã¸ã§ã¯ãã®å¥¥è¡ããè¨ç®ã§ããããã«ããããã«ãç§ãã¡ã®å¿ã«ååãªéããè¦ããã®ã«ååã§ãã ããã«ãããç¶²èã 2D 表é¢ã«ãããªãã«ããããããã3 次å ãç¥è¦ã§ããããã«ãªãã¾ãã
ããã¯ä¸ã®å³ã«ç¤ºããã¦ãã¾ãã ä¸ã®å³ã§ã¯ãããããã®ç®ããã¥ã¼ã¢ã¼ã®çæ£é¢ã«ãããããããã©ã®ããã«èªèãããã示ãã¦ãã¾ãã ãã®å³ã§ã¯ã説æã®ããã«ä¸é¨ã®ç¹ã§å¹æãèªå¼µãã¦ãã¾ãããæ¦å¿µã¯åãã§ãã åç®ã¯ãå¢çãç®ã®åã®åå¼§ãå½¢æããé åãè¦ã¾ãã ããããã®ç®ã¯é ã®ä¸å¿ç·ã®çå´ã¾ãã¯å対å´ã«ãªãã»ãããããããããã®ç®ã¯ã»ã¼åãè¦éãè¦ãã®ã§ããã®çµæãããããã®ç®ã¯ããã®åã«ããä¸çã®ãããã«ç°ãªãé¨åãå¥ã®è§åº¦ããè¦ããã¨ãã§ãã¾ãã
å·¦ç®ã¯ãããããä¸å¤®ããå°ãå·¦ã«è¦ãå³ç®ã¯ãããããä¸å¤®ããå°ãå³ã«è¦ã¾ãã ãã®çµæãå·¦ç®ã¯ãªãã¸ã§ã¯ãã®å·¦å´ãå°ãã ãè¦ããå³å´ãå°ãè¦ãã¾ããã éãåæ§ã§ãã ãããã® 2 ã¤ã®ç»åã¯ç¶²èã«ç¦ç¹ãåãããããçµæã®ä¿¡å·ã¯è¦ç¥çµãä»ãã¦å¾é èã®å¾é¨ã«ããè³ã®è¦è¦ç®è³ªã«éä¿¡ããã¾ãã
è³ã¯ãããã®ä¿¡å·ãå·¦ç®ã¨å³ç®ããåãåãããã¥ã¼ã¢ã¼ã®è³å ã«ä¸çã®åä¸ã®çµ±ä¸ããã 3D ç»åãæ§æãããã®ç»åãè¦ã¾ãã ã¾ããå·¦ç®ã¨å³ç®ã§è¦ããããã®ã®éãã«ãããè³ã¯ãªãã¸ã§ã¯ãã®å¥¥è¡ãã大ãããªã©ã«é¢ããå¤ãã®æ å ±ãæ¨æ¸¬ã§ãã¾ãã æ¨æ¸¬ããã奥è¡ãæ å ±ããé è¿æ³ãå½±ããããã®é¢ä¿ã®æå³ã®è¨æ¶ãªã©ã®ä»ã®æãããã¨çµã¿åããããã¨ã§ãç§ãã¡ã®å¨ãã®ä¸çã«ã¤ãã¦å¤ããçè§£ãããã¨ãã§ãã¾ãã
ãã¬ã¼ã ããã¼ãºããã¥ã¼ããã¬ã¼ã ãããã¡ã¼
ã·ã¼ã³ã®ããç¬éã®ç¶æ
ã表ã XRFrame ãåå¾ãããããã¥ã¼ã¢ã¼ãåºæºã«ãã¦ã·ã¼ã³å
ã®ãªãã¸ã§ã¯ãã®ä½ç½®ã決å®ããã¬ã³ããªã³ã°ã§ããããã«ããå¿
è¦ãããã¾ãã åç
§ç©ºéã«å¯¾ãããã¥ã¼ã¢ã¼ã®ä½ç½®ã¨æ¹åã¯ãXRFrame ã®ã¡ã½ãã getViewerPose() ãå¼ã³åºãã¦åå¾ãã XRViewerPose ã§è¡¨ããã¾ãã
XRFrame ã¯ãããªãã®ä¸çå
ã®ãªãã¸ã§ã¯ãã®ä½ç½®ã¾ãã¯æ¹åãç´æ¥è¿½è·¡ãã¾ããã 代ããã«ãä½ç½®ã¨æ¹åãã·ã¼ã³ã®åº§æ¨ç³»ã«å¤æããæ¹æ³ãæä¾ãããã¥ã¼ã¢ã¼ã®ä½ç½®ã¨æ¹åã®ãã¼ã¿ã XR ãã¼ãã¦ã§ã¢ããåéããããªããæ§æããåç
§ç©ºéã«å¤æãã¦ããã¬ã¼ã ã¬ã³ããªã³ã°ã³ã¼ãã«ã¿ã¤ã ã¹ã¿ã³ãä»ãã§é
ä¿¡ãã¾ãã ãã®ã¿ã¤ã ã¹ã¿ã³ãã¨ããªãç¬èªã®ãã¼ã¿ã使ç¨ãã¦ãã·ã¼ã³ã®ã¬ã³ããªã³ã°æ¹æ³ã決å®ãã¾ãã
ã·ã¼ã³ã 2 åã¬ã³ããªã³ã°ããå¾ï¼ãã¬ã¼ã ãããã¡ã¼ã®å·¦ååã« 1 åããã¬ã¼ã ãããã¡ã¼ã®å³ååã« 1 åï¼ããã¬ã¼ã ãããã¡ã¼ã¯ XR ãã¼ãã¦ã§ã¢ã«éä¿¡ããããã¬ã¼ã ãããã¡ã¼ã®åååã対å¿ããç®ã«è¡¨ç¤ºããã¾ãã ããã¯ãå¤ãã®å ´åï¼å¸¸ã«ã§ã¯ããã¾ããï¼ãç»åã 1 ã¤ã®ç»é¢ã«æç»ããã¬ã³ãºã使ç¨ãã¦ãã®ç»åã®æ£ããååãåç®ã«è»¢éãã¾ãã
3D ã WebXR ã«ãã£ã¦ã©ã®ããã«è¡¨ç¾ããããã«ã¤ãã¦è©³ããã¯ãWebXR ã«ãã 3D ã®è¡¨ç¾ãã覧ãã ããã
ã·ã¼ã³ãæã
ãã©ã¦ã¶ã¼ãã·ã¼ã³ã®æ¬¡ã®ãã¬ã¼ã ããã¤ã³ãã§ããããã«ãã¬ã¼ã ãããã¡ã¼ãæºåããã¨ããæ¥ãããrequestAnimationFrame() ã«æå®ãã颿°ãå¼ã³åºããã¾ãã ããã¯ãæç»ãããã¬ã¼ã ã®æå»ã¨ãã¬ã³ããªã³ã°ããå¿
è¦ã®ãããã¬ã¼ã ã®ã·ã¼ã³ã®ç¶æ
ã«é¢ãã詳細ãæä¾ãã XRFrame ãªãã¸ã§ã¯ããå
¥åã¨ãã¦åãåãã¾ãã
çæ³çã«ã¯ããã®ã³ã¼ãã 60 FPS ã®ãã¬ã¼ã ã¬ã¼ãã«ååãå¯è½ãªéãããã«è¿ãéããç¶æãããã¨ãå¿ è¦ã§ãã ãã® 1 ã¤ã®é¢æ°ã«ã¯ããªãã®ã³ã¼ãã ãã§ã¯ãªããã¨ãæãåºãã¦ãã ããã ã¡ã¤ã³ã¹ã¬ããããã¬ã¼ã èªä½ã®æç¶æéããããã¬ã¼ã ãããã®æéãé·ãå®è¡ããå¿ è¦ããªããã¨ã確èªããå¿ è¦ãããã¾ãã
åºæ¬çãªã¬ã³ãã©ã¼
ãã®ãã¼ã¸ã§ã³ã® WebXR ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ã§ã¯ãæ¯è¼çåç´ãªããã¸ã§ã¯ãã«æé©ãªé常ã«åç´ãªã¢ããã¼ãã使ç¨ãã¦ãã¾ãã ãã®çä¼¼ã³ã¼ãã¯ããã®ããã»ã¹ã®æ¦è¦ã示ãã¦ãã¾ãã
for each view in the pose's views list:
get the WebXR GL layer's viewport
set the WebGL viewport to match
for each object in the scene
bindProgram()
bindVertices()
bindMatrices()
bindUniforms()
bindBuffers()
bindTextures()
drawMyObject()
ç°¡åã«è¨ãã°ããã®å½¢å¼ã®ã¬ã³ãã©ã¼ã¯ãã¥ã¼åªå é ï¼view-first orderï¼ã使ç¨ãã¦ãã¾ãã ãã¹ã¦ã®ãªãã¸ã§ã¯ãã 1 ã¤ã®ãã¥ã¼ã«æç»ãã¦ãããåããªãã¸ã§ã¯ãã®ã»ãããä»ã®ãã¥ã¼ã«ã¬ã³ããªã³ã°ãã¦ãXR æ©å¨ã®ãã£ã¹ãã¬ã¤ãæ§æãã 2 ã¤ã®ãã¥ã¼ã®ãããããç¶ãã¦ã¬ã³ããªã³ã°ãã¾ãã ãã®çµæããªãã¸ã§ã¯ããæç»ããããã«å¿ è¦ãªãã¼ã¿ã®å¤ãã¯ããã¬ã¼ã ãã¨ã« 2 å GPU ã«éä¿¡ããããããå¤ãã®è¤è£½ããã使¥ãããã¾ãã ãã ããããã¯æ¢åã® WebGL ã³ã¼ãã®ç§»æ¤ãç°¡ç¥åããå¤ãã®å ´åããã®ä½æ¥ãè¡ãã®ã«ååãªã»ã©åªãã¦ãããããæåã«ãã®æ¹æ³ãè¦ã¦ããã¾ãã
ãã®ãã¬ã¼ã ã®ã·ã¼ã³ãæ§æããæ¬¡ã®ãªãã¸ã§ã¯ãã«é²ãåã«ãåãªãã¸ã§ã¯ããåç®ã«å¯¾ã㦠1 åãã¤ã2 åç¶ãã¦ã¬ã³ããªã³ã°ããï¼ã¤ã¾ãããªãã¸ã§ã¯ãåªå é ï¼object-first orderï¼ã§ã¬ã³ããªã³ã°ããï¼ä»£æ¿ã¢ããã¼ãã«ã¤ãã¦ã¯ããªãã¸ã§ã¯ãåªå é ã§ã¬ã³ããªã³ã°ãããã¨ã«ããæé©åãåç §ãã¦ãã ããã
ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ã®ãµã³ãã«
ãã®åºæ¬çãªãã¿ã¼ã³ã«å¾ãå®éã®ã³ã¼ããè¦ã¦ã¿ã¾ãããã ä¸è¨ã®ä¾ã§ã¯ããã®é¢æ°ã« myDrawFrame() ã¨ããååãä»ããã®ã§ãããã§ã¯å¼ãç¶ãããã使ç¨ãã¾ãã
let lastFrameTime = 0;
function myDrawFrame(currentFrameTime, frame) {
const session = frame.session;
let viewerPose;
// æéãæ¥ãããã¤ã³ããããæ¬¡ã®ãã¬ã¼ã ãã¹ã±ã¸ã¥ã¼ã«ãã¾ãã
animationFrameRequestID = session.requestAnimationFrame(myDrawFrame);
// ãã¥ã¼ã¢ã¼ã®ä½ç½®ã¨æ¹åã表ã XRViewerPose ãåå¾ãã¾ãã
// æåããå ´åããã¬ã¼ã ãã¬ã³ããªã³ã°ãã¾ãã
viewerPose = frame.getViewerPose(viewerRefSpace);
if (viewerPose) {
const glLayer = session.renderState.baseLayer;
gl.bindFrameBuffer(gl.FRAMEBUFFER, glLayer.framebuffer);
// ã¾ããè²ã¨å¥¥è¡ãã®ãã¬ã¼ã ãããã¡ã¼ãæ¶å»ãã¾ãã
gl.clearColor(0, 0, 0, 1.0);
gl.clearDepth(1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// æå¾ã®ãã¬ã¼ã ãã¬ã³ããªã³ã°ããã¦ããã®çµéæéãè¨ç®ãã¾ãã
// ãã®å¤ã使ç¨ãã¦ãã¢ãã¡ã¼ã·ã§ã³ãæå³ããã¨ããã®é度ã§å®è¡ãããããã«ãã¾ãã
const deltaTime = currentFrameTime - lastFrameTime;
lastFrameTime = currentFrameTime;
// 次ã«ãã»ãã·ã§ã³ã®ãã¥ã¼ãã¨ã«ã·ã¼ã³ã¬ã³ããªã³ã°ã³ã¼ãã1åå¼ã³åºãã¾ãã
for (const view of viewerPose.views) {
const viewport = glLayer.getViewport(view);
gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
myDrawSceneIntoView(view, deltaTime);
}
}
}
myDrawFrame() 颿°ã¯ãframe ãã©ã¡ã¼ã¿ã¼ã§æå®ããã XRFrame ãªãã¸ã§ã¯ããã XRSession ãåå¾ããã»ãã·ã§ã³ã® requestAnimationFrame() ã¡ã½ãããå¼ã³åºãã¦ã次ã®ãã¬ã¼ã ã®ã¬ã³ããªã³ã°ãããã«ã¹ã±ã¸ã¥ã¼ã«ãã¾ãã ããã«ãããããã«ãã¥ã¼ã«å
¥ããã¨ãä¿è¨¼ãããmyDrawFrame() 颿°ã®ãã®å復ã§è²»ããããæ®ãã®æéã¯ã次ã®ãã¬ã¼ã ãæç»ããã¿ã¤ãã³ã°ã«ã«ã¦ã³ãããã¾ãã
次ã«ããã¬ã¼ã ã® getViewerPose() ã¡ã½ããã使ç¨ãã¦ããã¥ã¼ã¢ã¼ã®ãã¼ãºï¼ãã®ä½ç½®ã¨æ¹åï¼ã表ã XRViewerPose ãªãã¸ã§ã¯ããåå¾ããWebXR ã»ãã·ã§ã³ã®ã»ããã¢ããä¸ã«ä»¥åã«åå¾ãã viewerRefSpace ãããã¥ã¼ã¢ã¼ã®åç
§ç©ºéãæ¸¡ãã¾ãã
ãã¥ã¼ã¢ã¼ã®ãã¼ãºãæã«ããã¨ããã¬ã¼ã ã®ã¬ã³ããªã³ã°ãéå§ã§ãã¾ãã æåã®ã¹ãããã¯ãWebXR æ©å¨ããã¬ã¼ã ãæç»ããããã¬ã¼ã ãããã¡ã¼ã¸ã®ã¢ã¯ã»ã¹ãåå¾ãããã¨ã§ãã ããã¯ãã»ãã·ã§ã³ã® renderState ãªãã¸ã§ã¯ãã® baseLayer ããããã£ããã¿ã¼ã²ãã WebGL ã¬ã¤ã¤ã¼ãåå¾ãã¦ããããã® XRWebGLLayer ãªãã¸ã§ã¯ããã framebuffer ãåå¾ãããã¨ã«ãã£ã¦è¡ããã¾ãã æ¬¡ã«ãgl.bindFrameBuffer() ãå¼ã³åºãã¦ãä»å¾ã®ãã¹ã¦ã®æç»ã³ãã³ãã®ã¿ã¼ã²ããã¨ãã¦ãã®ãã¬ã¼ã ãããã¡ã¼ããã¤ã³ããã¾ãã
次ã®ã¹ãããã¯ããã¬ã¼ã ãããã¡ã¼ãæ¶å»ãããã¨ã§ãã ã¬ã³ããªã³ã°ã³ã¼ãããã¬ã¼ã ãããã¡ã¼å
ã®ãã¹ã¦ã®ãã¯ã»ã«ãæ¸ãè¾¼ããã¨ãä¿è¨¼ããã¦ããå ´åã«éããçè«ä¸ã¯ãã®ã¹ããããã¹ãããã§ãã¾ãããããã©ã¼ãã³ã¹ã®å
¨ã¦ãæå¾ã¾ã§åºãåãå¿
è¦ããªãéããã¨ã«ãããã¹ã¦ã®ãã¯ã»ã«ã«è§¦ãã¦ãããã¨ã確å®ã«ããããã«ãæç»ãéå§ããåã«ãããã¯ãªã¢ãã¦ãæç»ãéå§ããã®ãä¸è¬çã«æãå®å
¨ã§ãã èæ¯è²ã¯ãgl.clearColor() ã使ç¨ãã¦å®å
¨ã«ä¸éæãªé»ã«è¨å®ãã¾ãã 奥è¡ãã®ã¯ãªã¢ã¯ãgl.cleardepth() ãå¼ã³åºã㦠1.0 ã«è¨å®ãã¾ãã ããã«ããããã¯ã»ã«ãå±ãããªãã¸ã§ã¯ããã©ãã ãé¢ãã¦ãããã«é¢ä¿ãªãããã¹ã¦ã®ãã¯ã»ã«ãã¯ãªã¢ããã¾ãã æå¾ã«ããã¬ã¼ã ã®ãã¯ã»ã«ãããã¡ã¼ã¨å¥¥è¡ããããã¡ã¼ã¯ãCOLOR_BUFFER_BIT 㨠DEPTH_BUFFER_BIT ã®ä¸¡æ¹ãè¨å®ããããããã¹ã¯ã渡ã㦠gl.clear() ãå¼ã³åºãã¦ä¸¡æ¹ã¨ãæ¶å»ãã¾ãã
WebXR ã¯ãã¹ã¦ã®ãã¥ã¼ã«åä¸ã®ãã¬ã¼ã ãããã¡ã¼ã使ç¨ãããã¥ã¼ä¸ã®ãã¥ã¼ãã¼ãã¯ãã¬ã¼ã ãããã¡ã¼å ã®åç®ã®è¦ç¹ãåé¢ããããã«ä½¿ç¨ããããããåç®ï¼ã¾ãã¯ä»ã®è¦ç¹ï¼ãåå¥ã«ã¯ãªã¢ããã®ã§ã¯ãªããåä¸ã®ãã¬ã¼ã ãããã¡ã¼ãã¯ãªã¢ããã ãã§æ¸ã¿ã¾ãã
次ã«ãåã®ãã¬ã¼ã ãã¬ã³ããªã³ã°ããã¦ããã®çµéæéã¯ãcurrentFrameTime ãã©ã¡ã¼ã¿ã¼ã§æå®ãããç¾å¨ã®æå»ãããæå¾ã®ãã¬ã¼ã ãã¬ã³ããªã³ã°ãããä¿åæå» lastFrameTime ãå·®ãå¼ãã¦è¨ç®ããã¾ãã çµæã¯ãæå¾ã®ãã¬ã¼ã ãã¬ã³ããªã³ã°ããã¦ããçµéããããªç§æ°ã示ã DOMHighResTimeStamp å¤ã§ãã ã·ã¼ã³ã®æç»ä¸ã«ãã®å¤ã使ç¨ãã¦ãã³ã¼ã«ããã¯ãä¸è²«ãããã¬ã¼ã ã¬ã¼ãã§èµ·åãããã¨æ³å®ããã®ã§ã¯ãªããå®éã®çµéæéãèæ
®ãã¦é©åãªè·é¢ã§ãã¹ã¦ãç§»åã§ããããã«ãã¾ãã ãã®çµéæéã¯å¤æ° deltaTime ã«ä¿åãããlastFrameTime ã®å¤ã¯ãã®ãã¬ã¼ã ã®æå»ã«ç½®ãæããããæ¬¡ã®ãã¬ã¼ã ã®å·®åãè¨ç®ããæºåãæ´ãã¾ãã
ããã§ã¯ãå®éã«ããããã®ç®ã«å¯¾ãã¦ã·ã¼ã³ãã¬ã³ããªã³ã°ããæãæ¥ã¾ããã ãã¥ã¼ã¢ã¼ã®ãã¼ãºã® views é
åå
ã®ãã¥ã¼ãå復å¦çãã¾ãã ã·ã¼ã³ã«å¯¾ããç®ã®ãã¼ã¹ãã¯ãã£ãï¼perspectiveï¼ã表ããããã® XRView ãªãã¸ã§ã¯ãã®ããããã«ã¤ãã¦ãæç»ãç¾å¨ã®ç®ã®å¯è¦ç»åã表ããã¬ã¼ã ãããã¡ã¼ã®é åã«å¶éãããã¨ããå§ããå¿
è¦ãããã¾ãã
XRWebGLLayer ã®ã¡ã½ãã getViewport() ãå¼ã³åºãã¦ãç¾å¨ã®ç®ã®ç»åç¨ã«äºç´ããã¦ãããã¬ã¼ã ãããã¡ã¼å
ã®é åã«æç»ãå¶éãããã¥ã¼ãã¼ããåå¾ãããã¨ã«ãããç®ã®ã³ã³ãã³ããã¬ã³ããªã³ã°ãã WebGL ãæºåãããã¨ããå§ãã¾ãã æ¬¡ã«ããã¥ã¼ãã¼ãã® X åç¹ã¨ Y åç¹ããå¹
ã¨é«ãã¨ã¨ãã« gl.viewport() ã«æ¸¡ãã¦ãWebGL ãã¥ã¼ãã¼ããä¸è´ããããã«è¨å®ãã¾ãã
æå¾ã«ãã¡ã½ãã myDrawSceneIntoView() ãå¼ã³åºãã¦ãå®éã« WebGL ã使ç¨ãã¦ã·ã¼ã³ãã¬ã³ããªã³ã°ãã¾ãã ããã«ã¯ãæç»ããç®ã表ã XRViewï¼éè¦ãããã³ã°ï¼perspective mappingï¼ãªã©ãå®è¡ããããï¼ã¨ deltaTime ãæ¸¡ãã¾ãã ããã«ãããã·ã¼ã³æç»ã³ã¼ãã¯ãæéã¨ã¨ãã«ç§»åãããªãã¸ã§ã¯ãã®ä½ç½®ã決å®ããã¨ãã«çµéæéãæ£ç¢ºã«è¡¨ããã¨ãã§ãã¾ãã
ãã¥ã¼ãå復ããã«ã¼ããçµäºããã¨ããã¥ã¼ã¢ã¼ã«ã·ã¼ã³ãæç¤ºããããã«å¿
è¦ãªãã¹ã¦ã®ç»åãã¬ã³ããªã³ã°ãããæ»ãã¨ããã¬ã¼ã ãããã¡ã¼ã¯ GPU ãçµç±ãã¦ãæçµçã«ã¯ XR æ©å¨ã®ãã£ã¹ãã¬ã¤ã«å°éãã¾ãã 颿°ã®ä¸é¨ã§ requestAnimationFrame() ãå¼ã³åºãã¦ããã®ã§ãã·ã¼ã³ã®ã¢ãã¡ã¼ã·ã§ã³ã®æ¬¡ã®ãã¬ã¼ã ãã¬ã³ããªã³ã°ããã¨ãã«ãã³ã¼ã«ããã¯ãããä¸åº¦å¼ã³åºããã¾ãã
ãã®ã¢ããã¼ãã®æ¬ ç¹
ãã®é¢æ°ã«è²»ããæéãã§ããã ãæå°éã«æãããã¨ãéè¦ã§ãããããç¶æ å¤åã®å¦çã«è²»ããæéãé·ãã»ã©ãå®éã«æç»ããæéãçããªãã¾ãã ãã®ãã¯ããã¯ã¯å°æ°ã®ãªãã¸ã§ã¯ãã«å¯¾ãã¦é常ã«ãã¾ãæ©è½ãã¾ãããåãªãã¸ã§ã¯ãã®ãã¹ã¦ã®ãã¼ã¿ã 2 åï¼å·¦ç®ã«å¯¾ã㦠1 åãå³ç®ã«å¯¾ã㦠1 åï¼åãã¤ã³ãããå¿ è¦ããããããç¶æ ã®èª¿æ´ããããã¡ã¼ã¨ãã¯ã¹ãã£ã¼ã®ã¢ãããã¼ããªã©ã«ãå¤ãã®æéãè²»ããã¦ãã¾ãã æ¬¡ã®ã»ã¯ã·ã§ã³ã§ã¯ããããã®ç¶æ ã®å¤åãå¤§å¹ ã«æ¸ãããç¹ã«ãªãã¸ã§ã¯ãæ°ãå¢ããã«ã¤ãã¦ãã¯ããã«é«éãªã¬ã³ããªã³ã°ã¢ããã¼ããæä¾ããã夿´ãããã¢ããã¼ãã«ã¤ãã¦èª¬æãã¾ãã
ãªãã¸ã§ã¯ãåªå é ã§ã¬ã³ããªã³ã°ãããã¨ã«ããæé©å
åä¸ã® WebGL ãã¬ã¼ã ãããã¡ã¼ã使ç¨ãã¦ãå·¦ç®ã¨å³ç®ã®ä¸¡æ¹ã®ãã¥ã¼ãåä¸ã®ãã¬ã¼ã ãããã¡ã¼ã«å«ããã¨ãã WebXR ã®ã¢ããã¼ãã®å©ç¹ã¯ãå¦çã®é åºãåé ç½®ãããã¨ã«ãããã¬ã³ããªã³ã°ããã©ã¼ãã³ã¹ãå¤§å¹ ã«åä¸ã§ãããã¨ã§ãã ç¹å®ã®ãã¥ã¼ï¼å·¦ç®ãªã©ï¼ã®ãã¥ã¼ãã¼ããè¨å®ããå·¦ç®ã§è¦ãããã¹ã¦ã®ãªãã¸ã§ã¯ãã 1 ã¤ãã¤ã¬ã³ããªã³ã°ããåãªãã¸ã§ã¯ãã«è¡ã£ãããããã¡ã¼ãåæ§æãã代ããã«ãåãªãã¸ã§ã¯ããããããã®ç®ã« 1 åãã¤ã2 åç¶ãã¦ã¬ã³ããªã³ã°ãã¾ãã ãããã£ã¦ã両æ¹ã®ç®ã«å¯¾ãã¦ãããã¡ã¼ãã¦ããã©ã¼ã ãªã©ã 1 åã»ããã¢ããããã ãã§æ¸ã¿ã¾ãã
çµæã®çä¼¼ã³ã¼ãã¯æ¬¡ã®ããã«ãªãã¾ãã
for each object in the scene
bindProgram()
bindUniforms()
bindBuffers()
bindTextures()
for each view in the pose's views list
get the XRWebGLLayer's viewport
set the WebGL viewport to match
bindVertices()
bindMatrices()
drawMyObject()
ãã®ããã«å¤æ´ãããã¨ã«ãããããã°ã©ã ãã¦ããã©ã¼ã ããããã¡ã¼ããã¯ã¹ãã£ã¼ããã®ä»ã®å¯è½æ§ã®ãããã®ã ãããã·ã¼ã³å ã®åãªãã¸ã§ã¯ãã«å¯¾ã㦠2 åã§ã¯ãªãããã¬ã¼ã ãã¨ã« 1 åã ããã¤ã³ããã¾ãã ããã«ãããæ½å¨çã«é常ã«å¤§ããªãã¼ã¸ã³ã§ãªã¼ãã¼ãããã忏ããã¾ãã
ãã¬ã¼ã ã¬ã¼ãã®å¶é
ä»ã®ã³ã¼ããå®è¡ããããã«ããå¤ãã®æéã確ä¿ããªãããç¶æãããã¨ãããã¼ã¹ã©ã¤ã³ã®ãã¬ã¼ã ã¬ã¼ãã確ç«ããããã«ãæå³çã«ãã¬ã¼ã ã¬ã¼ããå¶éããå¿ è¦ãããå ´åã¯ããã¬ã¼ã ãæå³çã«å®æçã«ã¹ããããããã¨ãã§ãã¾ãã
ä¾ãã°ããã¬ã¼ã ã¬ã¼ãã 50% ä¸ããã«ã¯ã1 ãã¬ã¼ã ããã«ã¹ããããã¾ãã
let tick = 0;
function drawFrame(time, frame) {
animationFrameRequestID = frame.session.requestAnimationFrame(drawFrame);
if (!(tick % 2)) {
/* ã·ã¼ã³ãæã */
}
tick++;
}
ãã®ãã¼ã¸ã§ã³ã®ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ã¯ãtick ã«ã¦ã³ã¿ã¼ãç¶æãã¾ãã tick ãå¶æ°ã®å¤ã§ããå ´åã«ã®ã¿ããã¬ã¼ã ãã¬ã³ããªã³ã°ããã¾ãã ãã®ããã«ãã¦ãã²ã¨ã¤ããã®ãã¬ã¼ã ã®ã¿ãã¬ã³ããªã³ã°ãã¾ãã
åæ§ã«ã!(tick % 4) ã使ç¨ãã¦ã4 ãã¬ã¼ã ãã¨ã«ã¬ã³ããªã³ã°ããçã
ãã§ãã¾ãã
ã¢ãã¡ã¼ã·ã§ã³ãçµéæéã«åããã
ã¬ã³ããªã³ã°ã³ã¼ã«ããã¯ã¯ãæ£å½ãªçç±ã§ time ãã©ã¡ã¼ã¿ãåãåãã¾ãã ãã® DOMHighResTimeStamp å¤ã¯ããã¬ã¼ã ã®ã¬ã³ããªã³ã°ãã¹ã±ã¸ã¥ã¼ã«ãããæå»ãç¤ºãæµ®åå°æ°ç¹å¤ã§ãã ã³ã¼ã«ããã¯ã®å®è¡ã¯æ£ç¢ºã« 1/60 ç§ééã§çºçããªããã â ããã¦å®éãã¦ã¼ã¶ã¼ã®ãã£ã¹ãã¬ã¤ã®ãã¬ã¼ã ã¬ã¼ããç°ãªãå ´åãä»ã®ã¬ã¼ãã§çºçããå¯è½æ§ããããã â ã³ã¼ããå®è¡ããã¦ããã¨ããåç´ãªäºå®ã«é ¼ã£ã¦ãæå¾ã®ãã¬ã¼ã ãã 1/60 ç§ã§ããã¨æ³å®ãããã¨ã¯ã§ãã¾ããã
ãã®ãããã¢ãã¡ã¼ã·ã§ã³ãç®çã®éåº¦ã§æ£ç¢ºã«ã¬ã³ããªã³ã°ãããããã«ãæä¾ããã¦ããã¿ã¤ã ã¹ã¿ã³ãã使ç¨ããå¿ è¦ãããã¾ãã ãããè¡ãã«ã¯ãæåã«è¡ãå¿ è¦ãããã®ã¯ãæå¾ã®ãã¬ã¼ã ãã¬ã³ããªã³ã°ããã¦ããçµéããæéãè¨ç®ãããã¨ã§ãã
let lastFrameTime = 0;
function drawFrame(time, frame) {
/* ... 次ã®ãã¬ã¼ã ã®ã¹ã±ã¸ã¥ã¼ã«ããããã¡ã¼ã®æºåãªã© ... */
const deltaTime = (time - lastFrameTime) * 0.001;
lastFrameTime = time;
for (const view of pose.views) {
/* åãã¥ã¼ã®ã¬ã³ããªã³ã° */
}
}
ããã¯ãåã®ãã¬ã¼ã ã®ã¬ã³ããªã³ã°æéãå«ã lastFrameTime ã¨å¼ã°ããã°ãã¼ãã«ï¼ã¾ãã¯ãªãã¸ã§ã¯ãããããã£ï¼ãç¶æãã¾ãã ãã®å ´åãæéã®å¤ã¯ããªç§åä½ã§æ ¼ç´ãããããã0.001 ãæãã¦æéãç§ã«å¤æãã¾ãã å ´åã«ãã£ã¦ã¯ãããã«ããå¾ã§æéãç¯ç´ã§ãã¾ãã ä»ã®ç¶æ³ã§ã¯ãããªç§åä½ã®æéãå¿
è¦ãªãããä½ã夿´ããå¿
è¦ã¯ããã¾ããã
çµéæéãæã«å ¥ããã°ãã¬ã³ããªã³ã°ã³ã¼ãã¯ããã¹ã¦ã®ç§»åãªãã¸ã§ã¯ããçµéæéå ã«ã©ãã ãç§»åããããè¨ç®ããææ®µãæã¡ã¾ãã ä¾ãã°ããªãã¸ã§ã¯ããå転ãã¦ããå ´åãæ¬¡ã®ããã«å転ãé©ç¨ã§ãã¾ãã
const xDeltaRotation =
xRotationDegreesPerSecond * RADIANS_PER_DEGREE * deltaTime;
const yDeltaRotation =
yRotationDegreesPerSecond * RADIANS_PER_DEGREE * deltaTime;
const zDeltaRotation =
zRotationDegreesPerSecond * RADIANS_PER_DEGREE * deltaTime;
ããã¯ããã¬ã¼ã ãæå¾ã«æç»ããã¦ãããªãã¸ã§ã¯ãã 3 ã¤ã®è»¸ã®ãããããä¸å¿ã«å転ããéãè¨ç®ãã¾ãã ããããªãã¨ãçµéæéã«é¢ä¿ãªããã·ã§ã¤ãã¯ãã¬ã¼ã ãã¨ã«æå®ãããéã ãå転ãã¾ãã ããã«ãããå¤ãã®å ´åãããªãã®ã¤ã£ãããçºçãã¾ãã
åã«å転ããã®ã§ã¯ãªããç§»åãããªãã¸ã§ã¯ãã«é©ç¨ãããåæ§ã®æ¦å¿µã§ã¯ã次ã®ããã«ãªãã¾ãã
const xDistanceMoved = xSpeedPerSecond * deltaTime;
const yDistanceMoved = ySpeedPerSecond * deltaTime;
const ZDistanceMoved = zSpeedPerSecond * deltaTime;
xSpeedPerSecondãySpeedPerSecondãzSpeedPerSecond ã¯ãããããã®ãªãã¸ã§ã¯ãã®é度ã®è»¸ã®æåãå«ã¿ã¾ãã ã¤ã¾ãã[xDistanceMoved, yDistanceMoved, zDistanceMoved] ã¯ããªãã¸ã§ã¯ãã®é度ã表ããã¯ãã«ã§ãã
ã·ã¼ã³ã®ã¢ãã¡ã¼ã·ã§ã³ã«é¢é£ãã追å ã®ã¿ã¹ã¯
ãã¡ãããã¬ã³ãã©ã¼ãééãããã³ã«çºçããå¯è½æ§ã®ããä»ã®ãã¨ãããã¾ãã æãä¸è¬ç㪠2 ã¤ã¯ãã¦ã¼ã¶ã¼å ¥åã®å¦çã¨ãã·ã¼ã³å ã®ãªãã¸ã§ã¯ãã®ã¦ã¼ã¶ã¼å¶å¾¡ç¶æ ãã¢ãã¡ã¼ã·ã§ã³ãã¹ãªã©ã®æ¢ç¥ã®è¦å ã«åºã¥ãã¦ããªãã¸ã§ã¯ãï¼ã¾ãã¯ãã¥ã¼ã¢ã¼ï¼ã®ä½ç½®ãæ´æ°ãããã¨ã§ãã
ã¦ã¼ã¶ã¼å¶å¾¡å ¥åã®å¦ç
WebXR ã¢ããªã±ã¼ã·ã§ã³ã®ä½¿ç¨ä¸ã«ã¦ã¼ã¶ã¼ãå ¥åãæä¾ããæ¹æ³ã¯ 3 ã¤ããã¾ãã ã¾ããWebXR ã¯ãXR ãã¼ãã¦ã§ã¢èªä½ã«çµ±åããã¦ããã³ã³ããã¼ã©ã¼ããã®å ¥åã®ç´æ¥å¦çããµãã¼ããã¦ãã¾ãã ãããã®å ¥åã½ã¼ã¹ã«ã¯ããã³ãã³ã³ããã¼ã©ã¼ãå å¦è¿½è·¡ã·ã¹ãã ãå é度è¨ã¨ç£åè¨ãªã©ã®ããã¤ã¹ãããã³ãã®ãããªä»ã®ããã¤ã¹ãå«ã¾ãã¾ãã
2 çªç®ã®ã¿ã¤ãã®å ¥åã¯ãXR ã·ã¹ãã ãä»ãã¦æ¥ç¶ãããã²ã¼ã ãããã§ãã ããã¯ãGamepad API ããç¶æ¿ãããã¤ã³ã¿ã¼ãã§ã¤ã¹ã使ç¨ãã¾ãããWebXR ãä»ãã¦ããããæä½ãã¾ãã
3 çªç®ã®æå¾ã®ã¿ã¤ãã®å ¥åã¯ããã¼ãã¼ãããã¦ã¹ããã©ãã¯ããããã¿ããã¹ã¯ãªã¼ã³ãé XR ã²ã¼ã ãããããã³ã¸ã§ã¤ã¹ãã£ãã¯ãªã©ã®å¾æ¥ã®é XR å ¥åããã¤ã¹ã§ãã
XR ãã¼ãã¦ã§ã¢ããç´æ¥åéã§ããæ¹åã¨ä½ç½®ã®æ å ±ã¯ãèªåçã«é©ç¨ããã¾ãã ãããã£ã¦ãèªåã§å¦çããå¿ è¦ãããã®ã¯ä»ã®ç¨®é¡ã®å ¥åã§ãã
- ãã¤ã³ãã£ã³ã°ããã¤ã¹ã®ã¿ã¼ã²ããã¨ãã¿ã³ã®æ¼ä¸
- ã²ã¼ã ãããã®å ¥å
- é XR å ¥åããã¤ã¹ã®å ¥å
WebXR ã使ç¨ãã¦ã·ã¼ã³ã表示ããéã«ã¦ã¼ã¶ã¼å ¥åãå¦çããæ¹æ³ã®è©³ç´°ã«ã¤ãã¦ã¯ãå ¥åã¨å ¥åã½ã¼ã¹ã®è¨äºãåç §ãã¦ãã ããã
ãªãã¸ã§ã¯ãã®ä½ç½®ã®æ´æ°
ã»ã¨ãã©ã®ï¼ãã¹ã¦ã§ã¯ããã¾ãããï¼ã·ã¼ã³ã«ã¯ãä½ããã®å½¢ã®ã¢ãã¡ã¼ã·ã§ã³ãå«ã¾ãã¦ãã¾ãã ã¢ãã¡ã¼ã·ã§ã³ã§ã¯ãç©äºãé©åã«åããäºãã«åå¿ãã¾ãã
ä¾ãã°ãä»®æ³ç¾å®ãæ¡å¼µç¾å®ã®ã²ã¼ã ã§ã¯ãæµã®éãã¬ã¤ã¤ã¼ãã£ã©ã¯ã¿ã¼ï¼NPCï¼ãã³ã³ãã¥ã¼ã¿ã¼ã«å¶å¾¡ãããã·ã¼ã³å ãç§»åããå ´åãããã¾ãã æéã®çµéã¨ã¨ãã«ä¸çã§ã®ä½ç½®ãå¤åããã ãã§ãªããå NPC ã«ã¯ç¸äºã«é¢é£ãã¦ç§»åããããã£ãã¼ãã¾ãã¯ã³ã³ãã¼ãã³ããããå¯è½æ§ãããã¾ãã ã¯ãªã¼ãã£ã¼ãæ©ãã¨è ã¨è¶³ãæºããé ãç´ æ©ãä¸ä¸ãããå転ãã髪ãè·³ãããæºããããããã£ã©ã¯ã¿ã¼ãå¼å¸ããã¨è´ä½ã¯æ¡å¼µå縮ãã¾ãã
ããã«ãåãã¦ããç©ä½ãæ§é ç©ãããããããã¾ããã ã¹ãã¼ãã²ã¼ã ã§ã¯ã空ä¸ã§å¼§ãæããã¼ã«ãããããã®åããã·ãã¥ã¬ã¼ãããå¿ è¦ãããã¾ãã ã¬ã¼ã·ã³ã°ã²ã¼ã ã§ã¯ãè»ããã®ä»ã®ä¹ãç©ããããè»è¼ªãå«ãã¦ã¢ãã¡ã¼ã·ã§ã³ããå¯åé¨åãããã¾ãã ã·ã¼ã³ã«æ°´ãããå ´åãæ³¢ç´ã¾ãã¯æ³¢ããªã¢ã«ã«è¦ããããã«ããå¿ è¦ãããã¾ãã ï¼ä¸é¨ã®ã¿ã¤ãã®ã²ã¼ã ã®å ´åï¼ãã¢ãå£ãåºãªã©ãæ§é ã®ä¸é¨ãåãã¦ããå ´åãããã¾ãã
ã¢ã¼ã·ã§ã³ã®ãã 1 ã¤ã®ä¸è¬çãªã½ã¼ã¹ã¯ããã¬ã¤ã¤ã¼èªèº«ã§ãã ã³ã³ããã¼ã«ããã®å ¥åãè§£éããå¾ï¼XR æå±ã¨ãã以å¤ã®ä¸¡æ¹ï¼ãã¦ã¼ã¶ã¼ã®åããã·ãã¥ã¬ã¼ãããããã«ããããã®å¤æ´ãã·ã¼ã³ã«é©ç¨ããå¿ è¦ãããã¾ãã 詳細ã¨ãããã©ã®ããã«æ©è½ãããã®å®å ¨ãªä¾ã«ã¤ãã¦ã¯ãç§»åãåããã¢ã¼ã·ã§ã³ã®è¨äºãåç §ãã¦ãã ããã
次ã®ã¹ããã
ã¬ã³ãã©ã¼ã使ããã â ã¾ãã¯ã宿ãã¦ããªãã¦ãæ©è½ãããã®ãããã° â ã«ã¡ã©ã¨ãã®ã·ã¼ã³å ¨ä½ã®åããå¦çãããã¨ãã§ãã¾ãã ããã«ã¤ãã¦ã¯ãWebXR ã®è¦ç¹ã¨ãã¥ã¼ã¢ã¼ã«é¢ããè¨äºã§èª¬æãã¦ãã¾ãã