개발하는 리프터 꽃게맨입니다.

[그래픽스] 가볍게 구현해본 3D 와이어 프레임 랜더링 본문

컴퓨터 그래픽스

[그래픽스] 가볍게 구현해본 3D 와이어 프레임 랜더링

파워꽃게맨 2024. 8. 11. 14:37

현재까지 2D 렌더러를 탄탄하게 만들었습니다.

 

2D 메시 컴포넌트입니다.

렌더링 하고자하는 게임 오브젝트에 해당 컴포넌트를 추가하여

Mesh2D에 정점과 정점을 잇는 인덱스 정보를 저장하여

정점 버퍼와 인덱스 버퍼를 만듭니다.

 

 

다음에는 RenderManager 라는 랜더링 코어 객체에 해당 오브젝트를 넘겨주어서 랜더링을 수행합니다.

 

저는 이 구조가 상당히 마음에 듭니다.

 

2D 객체를 그리는 시스템을 만들었으니 3D 객체도 만들어보겠습니다.

 

3D 객체를 만들기 위해서는 2D 시스템에서 사용하던 좌표 시스템의 차원을 한 단계씩 높여줘야 합니다.

 

Vertex는 3차원으로 정의되어야 하고

3차원에서 자유로운 선형 변환을 위해 3차원 벡터 및 4x4 정방행렬을 정의해야 합니다. 

 

 

그러면 또 Vertex3D를 정의해줘야겠죠.

 

 

그다음 3D 모델링 행렬을 만들어줘야 합니다.

3차원 이동변환은 4차원 전단변환으로 대체

3차원 크기변환은 대각성분을 일정한 비율로 바꿔주면 쉽게 정의할 수 있습니다.

 

 

그런데 회전 행렬은 만들기가 조금 까다롭습니다.

2차원 회전은 축이 1개인데 반해, 3차원 회전은 축이 무한하기 때문입니다.

 

3차원 변환을 위한 회전행렬을 만드는 방법은 대표적으로 3가지 방법이 있습니다.

 

1. 오일러 각 활용

2. 로드리게스 축-각 회전 공식

3. 회전 사원수 활용

 

편의상 오일러 각을 사용하도록 하겠습니다.

 

오일러 각을 이용해서 회전 행렬을 만드는 방법은 다음과 같습니다.

1. 표준 기저인 (1, 0, 0), (0, 1, 0) (0, 0, 1) 총 3개의 벡터를 각각 독립적인 회전축으로 사용한다.

2. 편의상 (1, 0, 0)을 피치(pitch), (0, 1, 0) 요(yaw), (0, 0, 1) 롤(roll) 이라고 부른다.

3. 요, 피치, 롤을 축으로하여 각각 독립적으로 회전시킵니다. 결과적으로 3개의 회전 행렬을 얻을 수 있습니다.

단, 주의점은 요을 축으로 잡고 돌렸을 때, 각이 증가하면 시계방향으로 회전하게 됩니다.

그러므로 요 축 회전행렬의 경우에는 공식을 조금 고쳐서 사용합니다.

 

4. 위 세 행렬을 곱하면 최종적인 회전 행렬을 얻어낼 수 있습니다.

행렬은 교환법칙이 성립하지 않기 때문에..

 

요롤피치

요피치롤

롤요피치

롤피치요

피치요롤

피치롤요

 

6가지 조합중에 하나 골라서 사용할 수 있습니다.

저는 롤 -> 피치 -> 요 순서로 회전을 수행하겠습니다.

 

제가 사용하는 렌더링은 열벡터 시스템을 사용하기 때문에

 

요 * 피치 * 롤 * 벡터

 

순으로 곱해야 합니다.

 

그러면 요 * 피치 * 롤을 계산해보겠습니다.

계산과정은 생략합니다.

 

 

솔직히 계산 귀찮아서 계산기 썼습니다.

 

행렬의 각 열은 각각 오브젝트의 로컬 기저 벡터가 됩니다.

 

오일러각을 정의하는 클래스입니다.

 

 

변형은 크기변환 -> 회전변환 -> 이동변환 순으로 하기때문에

모델링 행렬은 위와 같습니다.

 

대강 이런 모습

 

 

정점 버퍼와 인덱스 버퍼를 채워줍니다.

 

 

3D 렌더링 함수입니다.

z 값은 그대로 버리고 삼각형을 그리도록 했습니다.

z 값을 버리면 입체감이 사라집니다.

그러나 원근감을 보정해주려면 랜더링 코드를 많이 뜯어고쳐야하기 때문에 일단 3차원 물체를 랜더링만 해봅시다.

 

 

 

여기서 해결해야할 문제가 많습니다.

 

1. 뷰 행렬 제작

2. 후면은 눈에 보이지 않는 요소이므로, 후면부는 제거할 필요 있음

3. 원근감 부여

4. 깊이감 부여

 

등..

 

사실 가장 큰 문제점은 오일러 각 그 자체입니다.

오일러각은 회전을 수행하다보면 회전 자유도를 소멸시키는 특성이 있습니다. 

이를 짐벌락 현상이라고 합니다.

 

 

영상 중반부를 보면

롤이 증가하든, 요가 증가하든

같은 방향으로 회전하는 것을 볼 수 있습니다.

 

오일러 각을 사용해서 회전을 수행하면 이와같은 현상이 발생합니다.

그래서 앞서말했던 로드리게스 축-각 회전공식이나, 회전 사원수를 사용해야만 합니다.

 

단, 오일러각은 사람입장에서 이해하기 쉬운 숫자이기 때문에

엔진쪽에서 오일러각을 이용해서 회전을 처리

짐벌락을 없애기 위해서 내부에서는 회전 사원수를

최종적으로는 행렬곱을 위해서 회전 행렬로 바꿔주는 것이 최종 회전 시스템 구조입니다.

 

로드리게스 축-각 회전공식도 사용할 것이나, 연산 횟수가 너무 많기 때문에 사용하지 않습니다.

 

다른 것은 차차 업그레이드 해보기로하고 먼저 3D 카메라먼저 설계하도록 합시다.

 

 

3D 카메라 클래스입니다.

가장 중요한 것은 뷰 행렬을 얻어내는 겁니다.

 

현재 해당 카메라로 얻는 뷰 행렬은 카메라의 모델링 행렬의 역행렬입니다.

 

 

 

 

모델링 행렬에 뷰 행렬을 곱해서 최종적인 행렬을 만들어보겠습니다.

 

 

아마도 해당 뷰 행렬은 잘못된 행렬일 겁니다.

정상적으로 카메라가 구현되었다면 아무것도 그려지지 않는게 정상이겠죠

 

그러나 여전히 육면체가 잘 그려지는 이유는 z 값에 대한 처리를 하지 않아서 그렇습니다.

이에 대해서는 다음 포스팅에 다뤄보도록 하겠습니다.