Aframe ipd 관련 자료 검토
360VR
Aframe.js 에서 IPD 설정이 가능한지 여부를 확인이 필요했다. 우선 IPD가 무엇인지 알아보자.
IPD
IPD: Inter pupillary distance, 동공 거리
양쪽 눈의 동공 중심을 잇는 선의 거리. 사람에 따라 다소 차이는 있으나 대개 65mm이다. [네이버지식백과] 그런데 사람에 따라 동공사이의 거리가 조금씩 다르고 화면을 VR모드로 변경해서 카드보드를 쓰면 초점이 맞지 않을 수 있다.
그래서 VR기기에서 물리적 IPD의 거리를 조절할 수 있게 지원을 하거나 KRPANO처럼 소프트웨어에서 조절을 할 수 있도록 지원한다.
Aframe에서 IPD 검색
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 48 49 50 51 52 53 54 | /** * Assumes 2 cameras that are parallel and share an X-axis, and that * the cameras' projection and world matrices have already been set. * And that near and far planes are identical for both cameras. * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765 */ function setProjectionFromUnion( camera, cameraL, cameraR ) { cameraLPos.setFromMatrixPosition( cameraL.matrixWorld ); cameraRPos.setFromMatrixPosition( cameraR.matrixWorld ); var ipd = cameraLPos.distanceTo( cameraRPos ); var projL = cameraL.projectionMatrix.elements; var projR = cameraR.projectionMatrix.elements; // VR systems will have identical far and near planes, and // most likely identical top and bottom frustum extents. // Use the left camera for these values. var near = projL[ 14 ] / ( projL[ 10 ] - 1 ); var far = projL[ 14 ] / ( projL[ 10 ] + 1 ); var topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ]; var bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ]; var leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ]; var rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ]; var left = near * leftFov; var right = near * rightFov; // Calculate the new camera's position offset from the // left camera. xOffset should be roughly half `ipd`. var zOffset = ipd / ( - leftFov + rightFov ); var xOffset = zOffset * - leftFov; // TODO: Better way to apply this offset? cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale ); camera.translateX( xOffset ); camera.translateZ( zOffset ); camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale ); camera.matrixWorldInverse.getInverse( camera.matrixWorld ); // Find the union of the frustum values of the cameras and scale // the values so that the near plane's position does not change in world space, // although must now be relative to the new union camera. var near2 = near + zOffset; var far2 = far + zOffset; var left2 = left - xOffset; var right2 = right + ( ipd - xOffset ); var top2 = topFov * far / far2 * near2; var bottom2 = bottomFov * far / far2 * near2; camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 ); } | cs |
setProjectionFromUnion에서 IPD을 찾을 수 있었다. setProjectionFromUnion은 setProjectionFromUnion은 this.getCamera = function ( camera ) 함수에서 호출된다.
this.getCamera = function ( camera )
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 | this.getCamera = function ( camera ) { if ( isPresenting() ) { var parent = camera.parent; var cameras = cameraVR.cameras; var object = poseTarget || camera; updateCamera( cameraVR, parent ); for ( var i = 0; i < cameras.length; i ++ ) { updateCamera( cameras[ i ], parent ); } // update camera and its children object.matrixWorld.copy( cameraVR.matrixWorld ); var children = object.children; for ( var i = 0, l = children.length; i < l; i ++ ) { children[ i ].updateMatrixWorld( true ); } setProjectionFromUnion( cameraVR, cameraL, cameraR ); return cameraVR; } return camera; }; | cs |
하지만 관련 부분을 수정하고 테스트를 해봤지만 별다른 소득을 얻을 수 없었다. 나중에 알게된 사실이지만 WebXRManager에서 관련 부분을 다루고 있다고 본 것 같기도 하다.
IPD값 변경해 보기
직접 0.03~0.09로 수정을 해보고 렌더링 해봤는데 그 차이를 크게 느낄 수 없었다.