갬장장이
[3DGraphics] 4. Perspective projection
갬장장이
갬장장이의 코드 대장간
갬장장이
전체
오늘
어제
  • 분류 전체보기
    • 게임 연구소
    • 게임 제작
      • Banditors (2024~)
      • Rovenhell (2023)
      • Geophyte (2020~2021)
      • 아드레날린 러시 (2021)
      • Treadmill (2019)
      • 습작들 (2019~)
      • 그 외 (~2018)
    • 개발
      • 언리얼 엔진
      • 수학
      • 네트워크
      • 그래픽스
      • OpenGL
      • DirectX
    • 일상
    • 기타 제작

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

  • [공지] 블로그 안내

인기 글

최근 댓글

최근 글

hELLO · Designed By 정상우.
개발/그래픽스

[3DGraphics] 4. Perspective projection

2022. 7. 15. 19:46

현재 우리는 3차원 오브젝트를 orthographic한 방식으로 projection하고 있다.
즉 z축에 의한 원근을 무시한 채 그리고 있다.

z축이 영향을 주게 만들어보자. (Perspective projection)

perspective를 구현해보기 전에 우리의 시각이 현실에서 어떻게 작동하는지를 이해해보자.
우리는 왜 멀리 있는 물체를 더 "작다"고 인식할까?
pinhole camera를 사용해 직관적으로 이해할 수 있다.

image

만약 pinhole이 없이 그냥 물체로부터 바로 센서로 빛이 들어오게 하면 어떨까?

image


물체에서 반사된 여러 광선들이 전부 다 센서로 들어오게 되므로 센서 전체에 골고루 빛이 퍼져 상이 뿌옇게 보일 것이다.
pinhole은 이 중 특정 광선들만을 통과시킴으로써 상을 뚜렷하게 만들어준다.

image


여기서 또 한가지 눈여겨 볼 점은 우측에 있는 물체의 상이 센서의 좌측에 맺힌다는 것이다.
컴퓨터그래픽스에서 이를 해결하는 한가지 방법은 센서(image plane)를 초점(focal point) 앞으로 일정 거리만큼 당겨서 상이 물체의 위치와 같은 방향에 맺히게 하는 것이다.
이때 센서가 초점에서 떨어진 거리가 그 이전과 동일해야 상의 크기가 같다. (물론 이는 현실의 물리세계에서는 불가능한 방법이긴 하다)

image


이를 계산해보면 아래와 같다.
초점, 센서, 그리고 물체의 위치가 주어졌을 때, 삼각형의 닮음을 이용해 센서에 맺히는 상의 크기를 구할 수 있음을 볼 수 있다.

image


x' = x/z라는 식이 도출되는 것을 볼 수 있다.
x'은 상의 윗쪽 부분의 x좌표이고(아랫쪽부분은 0으로 고정이므로) x,z는 각각 물체의 x,z좌표이다.
(물론 이 식은 focal point가 0,0이고, 센서가 0,1 위치에 있다고 가정했을 때의 식이다.)

이때 만약 물체가 focal plane(초점이 있는 평면)에 가까워지면 가까워질수록(z->0) 상의 x'이 무한대로 커지는 것을 볼 수 있다.
focal plane을 넘어가면 상이 뒤집혀버리는 것을 볼 수 있다.
때문에 물체가 일정 거리를 넘지 못하게 clipping 해주는 과정이 필요한데, 이는 나중에 다시 다뤄보도록 하겠다.

image


또 한가지 유의할 점은, 기존 orthographic projection에서는 x가 우리의 시야 범위 내 (-1<=x<=1)에 있으면 모든 물체를 다 볼 수 있었지만,
이제는 -1 <= x/z <= 1 을 만족해야만 볼 수 있다는 점이다.

지금까지 2->1차원 projection을 다뤘는데, 3->2차원 projection도 거의 동일하다.
x' = x/z
y' = y/z
를 해주면 된다.

코드와 함께 살펴보자.

// 기존
// PubeScreenTransformer.h
Vec3& Transform( Vec3& v ) const
{
  v.x = (v.x + 1.0f) * xFactor;
  v.y = (-v.y + 1.0f) * yFactor;
  return v;
}

(참고:
xFactor = float( Graphics::ScreenWidth ) / 2.0f,
yFactor = float( Graphics::ScreenHeight ) / 2.0f
)

// 수정
// PubeScreenTransformer.h
Vec3& Transform( Vec3& v ) const
{
  const float zInv = 1.0f / v.z;
  v.x = (v.x * zInv + 1.0f) * xFactor;
  v.y = (-v.y * zInv + 1.0f) * yFactor;
  return v;
}

바뀐 건 screen transformation을 하기 전에 x및 y좌표에 z를 나눠주는(* zInv)것이다.
하지만 이상태로 코드를 실행하면 에러가 발생하는데,
이유는 큐브의 위치에서 찾을 수 있다. 우리는 큐브를 0,0,0위치에 1,1,1길이로 만든 후 이를 0,0,1만큼 이동했는데,
우리가 사용하고 있는 식 (x'=x/z, y'=y/z)은 focal point가 0,0,0이고 센서(image plane)가 (0,0,1)위치에 있다고 가정하고 있기 때문에
이 큐브의 일부분이 image plane의 뒷쪽으로 넘어가버리게 되어 상이 이상한 형태로 맺히게 된다.

image

때문에 큐브를 image plane에서 더 멀리 떼어놓으면 이 문제를 해결 가능하다.

image

코드로 보면 다음과 같다.

image


(단순히 큐브의 원점에서의 z축 거리를 더 멀게 늘려놓았다)
물론 이는 근본적인 해결책이 아니며, 나중에 clipping을 사용해 애초에 이런 현상이 발생하지 않도록 방지해볼 것이다.

image


이제 perspective projection이 정상동작하는 것을 볼 수 있다.

저작자표시 비영리 변경금지 (새창열림)

'개발 > 그래픽스' 카테고리의 다른 글

[3DGraphics] 6. Backface culling  (0) 2022.07.15
[3DGraphics] 5. Triangle rasterization  (0) 2022.07.15
[3DGraphics] 3. Rotation  (0) 2022.07.15
[3DGraphics] 2. 3D Space  (0) 2022.07.15
[3DGraphics] 1. Framework overview  (0) 2022.07.15
'개발/그래픽스' 카테고리의 다른 글
  • [3DGraphics] 6. Backface culling
  • [3DGraphics] 5. Triangle rasterization
  • [3DGraphics] 3. Rotation
  • [3DGraphics] 2. 3D Space
갬장장이
갬장장이
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.