DirectX - 투영 변환을 행렬로 표현
·
DirectX/Basic
여러 가지의 서로 다른 행렬을 일일히 찾는것은 어려우니 일관성을 위해서 투영 변환을 하나의 행렬로 표현하는 것이 좋습니다. 그러나 NDC를 변환하는 식 같은 경우 비선형이므로 행렬 표현이 존재하지 않습니다. 다행히 이 문제를 피해가는 방법이 있는데 바로, 공식을 선형인 부분과 비선형인 부분을 분리하는 것입니다.공식에서 비선형인 부분은 $z$로 나뉘는 연산입니다. 이 $z$ 좌표를 정규화를 하는 것입니다. 그러나 나중에 나누기를 수행할 때에는 원래의 $z$ 좌표가 필요하므로, 투영 변환 전에 원래의 입력 $z$ 좌표를 저장을 해두어야 합니다. 다행히 동차 좌표에는 남는 자리가 하나 있습니다. 즉, $z$좌표를 $w$좌표에 복사해 두는 것입니다. 행렬 곱셈의 관점에서 이는 3행 4열 성분을 0으로 설정하는..
DirectX - 정규화된 장치 좌표(NDC)
·
DirectX/Basic
앞 절에서는 투영된 점의 좌표를 시야 공간에서 계산했습니다. 시야 공간에서는 투영 창의 높이가 $2$이고 너비가 $2r$로 표기하는데 여기서 $r$의 의미는 종횡비를 의미합니다. 이 방식의 문제점은 투영 창의 크기가 종횡비에 의존하게 됩니다. 하드웨어가 투영 창의 크기가 관여하는 연산( 투영 창을 후면 버퍼로 변경하는 등)을 수행할 수 있으려면 하드웨어에게 종횡비를 알려 주어야 함을 뜻합니다. 만일 종횡비에 대한 이러한 의존성을 없앨 수 있다면 작업이 조금 더 수월해 질것입니다.해당 문제에 대한 해법은 투영된 점 $x$ 좌표성분을 다음과 같이 $[-r, r]$ 구건에서 $[-1,1]$로 비례시키는 것입니다.$$-r \le x' \le r$$$$-1 \le \dfrac{x'}{r} \le 1$$이러한 변환..
DirectX - 절두체
·
DirectX/Basic
시야 공간에서 투영의 중심을 원점에 두고 양의 $z$축을 바라보는 시야 절두체를 네 가지 수량을 이용해서 정의할 수 있습니다. 4 가지 수량이란 원점과 가까운 평면 사이의 거리 $n$, 먼 평면 사이의 거리 $f$, 수직 시야각 $a$, 종횡비 $r$입니다.시야 공간에서 가까운 평면과 먼 평면은 $xy$ 평면과 평행입니다. 따라서 원점과 그 평면들 사이의 거리는 그냥 $z$축 상의 거리일 뿐입니다. 종횡비(aspect ratio)는 $r = w/h$로 정의 되는데 여기서 $w$는 투영 창의 너비이고 $h$는 투영 창의 높이 입니다. 투영 창은 시야 공간 안의 화면의 2차원 이미지이고 이 이미지가 결국에는 후면 버퍼로 사용되므로, 투영 창의 너비와 높이의 비율을 후면 버퍼의 너비와 높이의 비율과 같게 만들..
DirectX - 시야 공간
·
DirectX/Basic
최종적으로 화면에 표시되는 것은 화면의 2차원 이미지이다. 그 이미지를 만들기 위해서는 화면에 가상의 카메라를 배치해야 합니다. 그 카메라는 월드에서 관찰자가 볼 수 있는 영역, 즉 월드에서 2차원 이미지를 생성해야하는 영역을 결정합니다. 그러한 카메라에 아래 그림과 같이 로컬 좌표계를 부여한다고 할때 이 좌표계가 바로 시야 공간 (View Space)으로, 시점 공간(eye space) 또는 카메라 공간 (camera space)이라고 부르기도 합니다.카메라는 이 공간의 원점에 놓여서 양의 $z$축을 바라봅니다. $x$축은 카메라의 오른쪽 방향이고 $y$축은 카메라의 위쪽 방향입니다. 렌더링 파이프라인의 후반부 단계들에서는 화면의 정점들을 세계 공간이 아니라 이 시야 공간을 기준으로 서술하는 것이 편한..
DirectX - 지역 공간과 세계 공간
·
DirectX/Basic
지역 공간(Local Space)와 세계 공간(World Space)DirectX에서 공간을 나누어서 작업을 하는데 크게 두 가지 지역 공간(local space, 국소 공간)과 세계 공간(world space)로 나뉘어 집니다. 지역 공간은 물체 자체의 위치나 회전량을 가지고 있으며 세계 공간은 렌더링된 세계의 특정한 지점을 기준으로 위치 좌표나 회전값을 계산하는 방식입니다. 좀 더 구체적으로는, 전역 공간 좌표계를 기준으로 한 국소 공간 좌표계의 원점과 축들의 위치 및 방향을 지정하고, 그에 해당하는 좌표 변경 변환을 수행해야 합니다. 지역 좌표계 기준의 좌표를 월드 좌표계로 변경하는 과정을 세계 변환(World Transform)이라고 부르고, 해당 변환 행렬을 세계 행렬(World Matrix)라..
DirectX - Input Assembler, IA 단계
·
DirectX/Basic
입력 조립기(input, assembler, IA) 단계는 메모리에서 기하 자료(정점들과 색인들)를 읽어서 기하학적 기본도형(삼각형, 선분 등)을 조립한다. 정점수학적으로 한 삼각형의 정점(vertex)은 두 변이 만나는 점입니다. 선분의 경우 선분의 양 끝점이 정점이고 하나의 점의 경우에는 그 점 자체가 정점입니다. DirectX의 정점은 그보다 훨씬 일반적입니다. DirectX의 정점은 본질적으로 공간적 위치 이외의 정보도 담을 수 있으며, 이를 통해서 좀 더 복잡한 렌더링 효과를 낼 수 있습니다. 예를 들어 조명을 구현하기 위해 정점에 노말 벡터를 추가하며, 텍스처를 적용하기 위해 정점에 덱스처 좌표를 추가 합니다. DirectX는 응용 프로그램이 자신만의 정점 형식을 정의 하여 정점의 성분들을 직..
DirectX - 색상 표현의 기초
·
DirectX/Basic
컴퓨터 모니터는 각 픽셀마다 빨간색, 녹색, 파란색 (RGB) 빛을 섞어서 방출합니다. 실제로 혼합된 빛이 눈으로 들어와서 망막의 한 지점을 때리면 그곳의 세포들이 자극되어서 신경 신호가 시신경을 따라 뇌에 전달됩니다. 그 신호를 해석해서 색을 인식하는데 빛의 혼합이 다르면 세포들이 자극되는 방식도 다르며 결과적으로 뇌는 서로 다른 색을 인식하게 됩니다. 이처럼 RGB 값들로 색상을 표현하는 방식에 쉽게 익숙해지는 한 가지 방법은 여러 가지 색을 만들어 보는 것입니다. 모니터가 방출하는 적, 녹, 청색광의 세기에는 상한과 하한이 존재합니다. 빛의 세기를 나타낼때에는 0에서 1까지로 정규화된 값을 사용하는 것이 편리합니다. 0은 빛이 전혀 없는 것이고 1은 빛의 세기가 최대인 것이다. 그리고 그 중간의 값..
DirectX - 메세지 처리부
·
DirectX/Basic
응용 프로그램 프레임워크는 창 메시지 처리부를 최소한의 형태로만 구현하고 있습니다. 응용 프로그램 코드의 핵심부는 창 메시지가 전혀 없을때 실행 됩니다. 그래도 반드시 처리 해야 할 주요 메시지들이 있긴 하지만 너무 길기에 코드 전체를 제시하지는 않고, 대신 구현이 처리하는 각 메시지에 깔린 의도만 설명하겠습니다.WM_ACTIVATE구현이 처리하는 첫 메세지는 `WM_ACTIVATE`입니다. 이 메시지는 응용 프로그램이 활성화 또는 비활성화 될 때 전달 됩니다. 이 프레임 워크는 해당 메시지를 다음과 같이 처리합니다.case WM_ACTIVATE: if (LOWORD(wParam) == WA_INACTIVE) { mAppPaused = true; mTimer.Stop(..
Buffer
·
DirectX/Basic
Direct X에서의 버퍼(Buffer)는 형식화된 데이터의 컬렉션입니다. GPU에 전달할 데이터를 임시로 저장해 두는 메모리 공간이며 CPU가 GPU에게 건네주는 데이터 모음이라고 볼 수 있습니다. 버퍼를 사용하여 위치 벡터나 일반 벡터, 버텍스 버퍼의 텍스쳐 좌표, 인덱스 버퍼의 인덱스 또는 디바이스 상태를 비롯한 다양한 데이터를 저장할 수 있습니다. 다이렉트 X에서는 보통 `ID3D1Buffer` 인터페이스에 의해 캡슐화되어 있습니다.Vertex BufferVertex Buffer에는 3D 버텍스, 즉 3D 정점을 지정하는데 필요한 데이터가 포함되어 있습니다. 정점의 위치 좌표나 정점의 색상과 같은 데이터를 가지고 있으며 , 삼각형이나 사각형 같은 도형을 그려낼때 사용하게 됩니다.버텍스 버퍼는 `I..
Device
·
DirectX/Basic
DeviceDevice는 GPU(그래픽 카드)를 추상화한 API 객체이며, DirectX에서 GPU가 할 수 있는 기능을 사용자가 접근할 수 있도록 도와주는 인터페이스입니다. Direct3D 11 기준으로 `D3D11CreateDevice`를 호출해서 생성할 수 있습니다.ID3D11Device* device = nullptr;ID3D11DeviceContext* context = nullptrD3D11CreateDevice( nullptr, // 기본 어댑터 D3D_DRIVER-TYPE_HARDWARE, // GPU 사용 nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, // 디바이스 생성 nullptr,..