반응형

이번 장에서는 게임을 제작하면서 주로 다루었던 착시효과를 어떻게 구현하였는지 다룬다.

 

주 목표 효과: 어느 한 물체가 게이머로부터 거리가 변할 시 보이는 크기는 그대로인 현상

-> 즉, 원래 현실 3D 세계라면 어떠한 물체가 거리가 멀어질수록 작아져야 하지만, 주인공의 초능력으로 인해 거리가 멀어지는 만큼 물체가 크기가 진다.

 

그래도 다행인 점은 시야에 따른 착시현상이지만, 게임의 장르는 FPS(일인칭시점, 물론 총싸움을 진행하진 않는다.)로 캐릭터 머리에 카메라가 딱 고정되는 형태이다. 따라서, 캐릭터 머리에 해당하는 착시만 구현하면 이 게임의 목표착시구현은 종료된다.

 

이번 장에서는 그림설명부터 진행하겠다.

제 1가설: FOV 에 따라 물체를 비율 변환시킨다.

필자는 시야에 대한 착시이기에 FOV부터 알아보았다. 이 가설의 결론부터 말하자면 Fail이긴 하다.

 

FOV(Field of View): 우리말로 '시야장' 정도로 직역되는 이 단어는 '시야각'을 의미. 즉, 눈을 떴을 때 보이는 영역을 의미.

 

내 '앞'에 있는 시야각 부분을 꽉 채운 영사 기술이 있는데, 이를 아이맥스라 부른다. 물론, 아이맥스는 논외며 FOV를 이해하기 위해 아이맥스를 꺼내보았다.

 

https://terms.naver.com/entry.naver?docId=1986928&cid=40942&categoryId=33091

 

아이맥스

일반 영화의 스크린보다 10배 정도 큰 초대형 스크린 방식을 이용한 촬영과 영사 시스템을 말한다. 사람의 눈이 미칠 수 있는 최대의 시각 폭을 뜻하는 '아이 맥시멈(Eye Maximum)' 또는 최대 이미지

terms.naver.com

더보기

요약 - 일반 영화의 스크린보다 10배 정도 큰 초대형 스크린 방식을 이용한 촬영과 영사 시스템을 말한다.

사람의 눈이 미칠 수 있는 최대의 시각 폭을 뜻하는 '아이 맥시멈(Eye Maximum)' 또는 최대 이미지를 뜻하는 '이미지 맥시멈(Image Maximum)'의 약자이다. 보통 일반적인 영화의 스크린보다 10배 정도 큰 초대형 스크린의 영화로 지칭되지만, 본래는 캐나다 영화제작사 아이맥스(IMAX Corporation)의 필름 포맷을 말하며, 이 필름 포맷을 사용하여 촬영한 영화를 아이맥스 영화라 한다.

최초의 아이맥스 영화는 아이맥스사의 설립자인 그램 퍼거슨(Graeme Ferguson)·로먼 크로이터(Roman Kroitor)·로버트 커(Robert Kerr)·윌리엄 쇼(William Shaw) 등이 일본 후지그룹의 의뢰를 받아 제작한 《타이거 차일드 Tiger Child》로, 1970년 일본 오사카국제박람회에서 첫 선을 보였다. 한국에서는 1985년 6월 서울 여의도의 63빌딩에 아이맥스 영화관이 처음으로 개장하였고, 1986년 7월에는 국내 최초의 아이맥스 영화 《아름다운 대한민국》이 제작되었다.

아이맥스 영화를 촬영하기 위해서는 전용 카메라와 전용 필름이 필요하고, 이를 상영하기 위해서는 전용관이 있어야 한다. 촬영 단계에서부터 일반적으로 사용하는 35㎜ 필름이 아닌 70㎜ 대형 필름(70㎜ x 48.5㎜)을 사용하며, 필름이 카메라 안에서 수평으로 이동하며 퍼포레이션(perforation) 홀 15개마다 1프레임씩 담는데, 1프레임당 크기가 35㎜ 표준 필름의 9배, 일반 70㎜ 영화의 1.5배에 해당한다. 음향도 고출력 6채널로 구성하여 생생한 음질을 구현한다.

상영관은 스크린이 관객을 향하여 5도 정도 기울어져 있고, 객석은 30∼45° 각도의 층계식이다. 아이맥스 영화의 스크린 표준은 일반 35㎜ 영화의 약 10배에 이르는 가로 22m, 세로 16m이지만, 상영관에 따라 차이가 있다. 어안 렌즈로 촬영하여 반구형 돔 모양의 스크린에 영사하는 전용관을 옴니맥스(Omnimax) 또는 아이맥스돔(Imax dome)이라고 하는데, 영사기를 극장 안의 중앙에 놓고 경사형 돔 스크린에 상영하며 관객은 좌석에서 반쯤 누운 자세로 거의 180도 선상의 반구 안에서 거대한 영상을 관람한다.

아이맥스 영화는 비용이 많이 들고 상영 장소도 제한적이어서 일반 극영화를 제작하기에는 어려움이 있다. 이러한 한계를 극복하기 위해 일반 영화 필름을 디지털 신호를 이용한 보정 과정을 거쳐 아이맥스 필름 포맷으로 변환하는 아이맥스 DMR(Digital Media Remastering) 기법이 등장하였고, 일반 영화와 아이맥스 DMR 영화를 모두 상영할 수 있도록 기존의 멀티플렉스 영화관을 개조한 아이맥스 MPX가 있다.

[네이버 지식백과] 아이맥스 [IMAX] (두산백과 두피디아, 두산백과)

 

FOV에 대해 얼추 감이 잡혔다면, 왜 시야각을 세로로 측정하였는지 설명할 시간이다.

 

당연하지만, FOV는 가로 뿐 아니라 세로도 존재한다. 즉, 크기에 대한 착시현상을 온전히 구현하기 위해선 가로 뿐 아니라 세로도 구현해야한다는 결론에 다다른다.

 

하지만, 필자의 실험결과 FOV의 비율로 사물을 거리에 맞게 늘이고 줄여도 착시현상은 일어나지 않았다... 오히려 역 원근효과(멀어질수록 크기가 커진다.)가 발생했다. 계산 결과 물체를 FOV 비율로 늘릴 경우 착시현상에 '수렴'하는 결과를 낳았다.

 


 

제 2가설: 눈의 위치와 물체의 최 상단의 각도의 비율을 찾아 적용한다.(결론은 Success)

우리는 수렴하는 결과를 원하는 것이 아니라 지속적으로 착시현상이 일어날 수 있게 해야 한다. 그 기준이 물체가 보이는 최고(最高) 각을 알아낸다. 후에 거리를 변경할 시 그 각을 기준으로 하여 삼각형의 닮음 비례를 이용하면 높이 즉, 한 변의 길이를 구할 수 있다. 이 점을 이용하여 모든 변의 길이, 위치의 수정을 하면 될 것이다.

 

단, 이 가설에는 문제점이 존재하는데 바로 눈높이보다 낮은 위치에 있게 되면 찾아야 할 물체가 보이는 각도가 로 된다.

이 점을 고려하여 물체를 눈높이 상으로 맞추고 효과를 고려해야 할 것이다. 단, 여기서 눈높이 상으로 맞추는 기준점은 물체의 중심점으로 한다.

 

최고각의 개념

 

뭐, 부호 판단은 차후에 계산하기로 하고 우선 사진의 아래 경우 처럼 최고 각이 눈 위에 있을 때를 가정하고 수식을 짠다.

 

원근 수식 설정

 

  1. 물체를 확대를 시킨다는 가정 하에 A를 같은 최고각으로 약 dx만큼 후퇴했을 경우 B 라 칭한다. 그 좌표를 각각 (x, y, z), (px, py, pz)로 칭한다. 여기서 해당 좌표축의 중심은 카메라, 즉 캐릭터의 눈이다.
  2. A, B의 최고각은 서로 같으므로 기준이 되는 A의 좌표를 활용하여 그 각도를 구한다. 단, 물체의 최고점을 알아내야 하는데 그 최고점 P의 좌표는 다음과 같다.
    P = ((distance – m/2) * Cosb, 2 * y, (distance – m/2) * Sinb))m = 물체의 X Scale, distance = 물체와 캐릭터의 거리
    따라서 최고각, a는 최고점 P와 A의 중심좌표에서 높이를 뺀 (x, 0, z)로 구한다.
  3. 이 점을 활용하여 삼각형의 닮음 조건으로 B의 높이를 알아낸다. 후에 그 비례크기로 나머지 변의 길이를 적용시킨다. 여기서 높이를 알아내는 이유는 A의 각도 a와 B의 각도 a는 같기 때문에 닮은 비례를 바로 적용시킬 수 있기 때문이다. 이 성질을 이용하여 dx만큼 떨어진 B의 높이를 구할 수 있다.m = ((distance + dx) * tan a) / mm = B의 높이, m = A의 높이 (집을 수 있는 물체라면 부피를 가지고 있다.)다른 변의 길이는 닮음 이기 때문에 역시 같은 꼴을 취한다.x = ((distance + dx) * tan a) / x

간단하게 수식을 코드로 옮겨보았다.

 

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
//물체 인식 아래 벡터 입력
axz = new Vector3(Get_Hit_Pos(obj).x, .0f, Get_Hit_Pos(obj).z)
    //카메라의 위치를 원점으로 이동시켜 측정
    //물체 위치에서 현재 위치를 빼면 원점으로 이동됨
    - new Vector3(Get_Pos().x, .0f, Get_Pos().z);
 
//사인, 코사인 각도 - 아래 시야 너비를 담당
float axz_Ang = Get_Ang(Vector3.right, axz);
 
//물체 인식 높이 벡터 입력
axzh = Vector3.Normalize(
    new Vector3    (
        (distance - Get_Hit_Pos(obj).z / 2* Mathf.Cos(axz_Ang * Mathf.Deg2Rad,
        Get_Hit_Loc(obj).y - Get_Pos().y,
        (distance - Get_Hit_Pos(obj).z / 2* Mathf.Sin(axz_Ang * Mathf.Deg2Rad
                )
 
        //카메라의 위치를 원점으로 이동시켜 측정
        //물체 위치에서 현재 위치를 빼면 원점으로 이동 됨
        - Get_Pos());
 
//탄젠트 각도 - 높이를 담당
float axzh_Ang = Get_Ang(axz, axzh);
 
public void Add_Pos(Vector3 p) { transform.position += p; }
public float Get_Ang(Vector3 from, Vector3 to)
{
    //xz면 기준 각도
    if(from == Vector3.right)
    {
        if(to.z >= 0)     return Vector3.Angle(from, to);
        else            return Vector3.Angle(from, to) * (-1);
    }
 
    return 0;
}
cs

 

 

 

이번 포스팅은 구현 영상을 끝으로 마무리 하겠다.

간략한 설명을 하자면, 물병이 너무 작아 못 먹는 상황에서 주인공의 능력을 활용해 물병을 키우는 모습이다.

 

반응형
Posted by Kestone Black Box
,