카메라 원리

 

Perspective와 Orthographic의 차이

 

 Camera 오브젝트의 Inspector 창에서 Projection의 두 가지 옵션이 있습니다. Percpective Orthographic이 있는데 Percpective는 사물에 대해 원근감과 공간감을 잘 표현하여서 보여주고, Orthographic은 사물에 대해서 원근감과 공간감 없이 표현을 해줍니다. 보통 2D나 2.5D를 제작할 시에는 Orthographic을 사용하여 제작합니다.

Perspective vs Orhographic

뷰 절두체 이해

절두체 는 피라미드 같은 모양의 윗부분을 밑면에 병렬로 잘라낸 입체 형상을 가리킵니다. 이는 원근(Perspective) 카메라에 의해 보여지고 렌더링되는 영역의 형상입니다.

원거리 절단면과 근거리 절단면은 모두 카메라의 XY 평면에 평행하게 위치하고 있으며, 만일 어떤 것이 근거리 절단면보다 카메라에 근접하거나 원거리 절단면보다 카메라에 멀리 떨어져있는 경우에는 렌더링되지 않습니다.

 

카메라에서 일정 거리 떨어진 절두체의 크기

카메라에서 일정 거리 떨어진 뷰 절두체의 교차 영역은 가시 영역을 구성하는 월드 공간에서 사각형으로 정의됩니다. 떨어진 거리를 알고 있으면 사각형의 크기를 계산할 수 있고, 사각형의 크기를 알고 있으면 떨어진 거리를 계산할 수 있기 때문에, 이를 유용하게 활용할 수 있습니다. 예를 들어, 움직이는 카메라가 항상 플레이어와 같은 특정 오브젝트를 샷 안에 계속 온전하게 담아내야 할 때, 오브젝트가 잘리지 않도록 카메라의 적정 거리를 유지할 수 있습니다.

일정 거리만큼 떨어진 절두체의 높이(두 값 모두 월드 단위)는 다음 공식을 통해 구할 수 있습니다.

 var frustumHeight = 2.0f * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);

또한 이 과정을 반대로 하면 특정 절두체 높이일 때의 거리를 계산할 수 있습니다.

 var distance = frustumHeight * 0.5f / Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);

거리와 높이를 모두 알고 있을 때에는 FOV 각도를 계산할 수도 있습니다.

 var camera.fieldOfView = 2.0f * Mathf.Atan(frustumHeight * 0.5f / distance) * Mathf.Rad2Deg;

각 계산식의 결과를 얻으려면 절두체의 높이를 알아야 하며, 절두체의 높이는 절두체의 너비를 이용하여 쉽게 구할 수 있습니다(절두체의 높이를 이용하여 너비를 계산할 수도 있음).

var frustumWidth = frustumHeight * camera.aspect;
var frustumHeight = frustumWidth / camera.aspect;

카메라에서 나오는 레이

Ray

public Ray (Vector3 origin, Vector3 direction);

origin에서 출발해서 direction을 따라가는 광선을 만듭니다. 

 Ray ray = new Ray(transform.position, transform.forward);

 

카메라의 뷰에서 모든 점은 월드 공간의 하나의 선에 대응됩니다. 때로는 그 선의 수학적인 표현을 사용하는 것이 편리한 경우가 있으며 Unity는 이것을 레이(Ray) 오브젝트로 제공할 수 있습니다. 레이는 항상 뷰 내의 한 점에 부합하므로 Camera 클래스는 ScreenPointToRay  ViewportPointToRay 함수를 제공합니다. 이 둘의 차이는 ScreenPointToRay가 점을 픽셀 좌표를 필요로 하는 반면 ViewportPointToRay는 0..1(뷰에서 0이 왼쪽 또는 아래쪽 1이 오른쪽 또는 위쪽) 범위의 정규화된 좌표를 요구한다는 점입니다. 이 각각의 함수는 원점과 원점으로부터 나가는 선의 방향을 나타내는 벡터로 구성된 레이의 값을 반환합니다. 레이는 카메라의 transform.position 포인트 대​​신 근접 클리핑 평면을 기점으로 하고 있습니다.

레이캐스팅(Raycasting)

카메라를 통한 레이의 가장 일반적인 사용 방법은 씬에 Raycast를 실행하는 것입니다. 레이캐스트는 가상의 “레이저 빔”을 원점에서부터 레이에 따라 씬 안의 콜라이더에 충돌할 때까지 보냅니다. 그 다음 오브젝트와 RaycastHit 오브젝트의 충돌된 점에 대한 정보를 반환합니다. 이것은 스크린상 나타난 이미지를 기반하여 오브젝트가 어디에 위치하는지 찾는 유용한 방법입니다. 예를 들어, 마우스 포지션에 있는 오브젝트는 다음 코드로 확인할 수 있습니다.

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public Camera camera;

    void Start(){
        RaycastHit hit;  //충돌정보를 받아오는 변수
        Ray ray = camera.ScreenPointToRay(Input.mousePosition);  //레어저벡터
        
        if (Physics.Raycast(ray, out hit)) { //레이저를 쏨
            Transform objectHit = hit.transform;
            
            // Do something with the object that was hit by the raycast.
        }
    }
}

레이를 따라 카메라 이동

때로는 화면의 한 포지션에 반응하는 레이를 설정하고 카메라를 레이에 따라 이동시키는 것이 유용할 때가 있습니다. 예를 들어, 사용자가 오브젝트를 마우스로 선택하여 동일한 화면 위치를 “고정”하면서 줌인할 경우가 있습니다(이것은 카메라가 전술 지도를 볼 때 유용할 수 있습니다). 이 작업을 위한 코드는 매우 간단합니다.

using UnityEngine;
using System.Collections;

public class ExampleScript : MonoBehaviour {
    public bool zooming;
    public float zoomSpeed;
    public Camera camera;

    void Update() {
        if (zooming) {
            Ray ray = camera.ScreenPointToRay(Input.mousePosition);
            float zoomDistance = zoomSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
            camera.transform.Translate(ray.direction * zoomDistance, Space.World);
        }
    }
}

+ Recent posts