돌리 줌(Dolly Zoom) (일명 "트롬본" 효과)

돌리 줌(Dolly Zoom)은 카메라가 동시에 목표 대상으로 이동하고 그것으로부터 줌 아웃 하는 매우 잘 알려진 시각효과입니다. 그 결과로 해당 대상은 거의 같은 크기를 유지하나 씬(scene)안에 있는 다른 대상들은 관점이 변화하게 됩니다. 미묘하기는 하지만, 돌리 줌은 씬 내에서 목표 대상이 유일하게 이미지 내에서 위치를 변경하지 않으므로 목표대상을 강조하는 효과를 가져옵니다. 또는 줌을 의도적으로 신속하게 수행하여 방향상실의 느낌을 창출할 수도 있습니다.

수직적으로 프러스텀(frustum)에 딱 맞는 오브젝트는 화면 상에서 보이는 것처럼 뷰(view)의 전체 높이를 차지할 것입니다. 이는 해당 오브젝트가 카메라로부터의 거리가 얼마이든 뷰(view)의 필드가 어떻든 상관없이 그러합니다. 예를 들면, 사용자는 카메라를 오브젝트에 더 가까이 움직일 수 있으나 뷰의 필드를 넓혀서 오브젝트가 여전히 프러스텀의 높이 내에 딱 들어맞게 할 수 있습니다. 이 특정 오브젝트는 스크린상에 같은 사이즈로 나타나지만 다른 모든 것은 거리와 FOV가 변함에 따라 크기가 변경될 것 입니다.

코드 내에서 효과를 창출하는 것은 줌의 시작 시점에서 오브젝트의 위치에 프러스텀의 높이를 저장하는 문제입니다. 그리고, 카메라가 움직임에 따라, 새로운 거리를 찾고, FOV는 오브젝트의 위치에 같은 높이로 유지되도록 조정됩니다. 이는 다음 코드를 통해 수행할 수 있습니다:-

var target: Transform;
 
private var initHeightAtDist: float;
private var dzEnabled: boolean;
 
 
// 카메라로부터 주어진 거리에서 프러스텀의 높이를 계산합니다.
function FrustumHeightAtDistance(distance: float) {
	return 2.0 * distance * Mathf.Tan(camera.fieldOfView * 0.5 * Mathf.Deg2Rad);
}
 
 
// 주어진 거리에서 주어진 프로스텀의 높이를 구하기 위해 필요한 FOV을 계산합니다.
function FOVForHeightAndDistance(height: float, distance: float) {
	return 2 * Mathf.Atan(height * 0.5 / distance) * Mathf.Rad2Deg;
}
 
 
// 돌리 줌(dolly zoom)효과를 시작합니다.
function StartDZ() {
	var distance = Vector3.Distance(transform.position, target.position);
	initHeightAtDist = FrustumHeightAtDistance(distance);
	dzEnabled = true;
}
 
 
// 돌리 줌 효과를 끕니다.
function StopDZ() {
	dzEnabled = false;
}
 
 
function Start() {
	StartDZ();
}
 
 
function Update () {
	if (dzEnabled) {
		// 새로운 거리를 측정하고 그에 따른 FOV을 재 조정합니다.
		var currDistance = Vector3.Distance(transform.position, target.position);
		camera.fieldOfView = FOVForHeightAndDistance(initHeightAtDist, currDistance);
	}
 
	// 위/아래 화살표를 사용하여 카메라를 안팎으로 움직일 수 있게 하는 단순한 제어장치
	transform.Translate(Input.GetAxis("Vertical") * Vector3.forward * Time.deltaTime * 5);
}

역링크