Presentation is loading. Please wait.

Presentation is loading. Please wait.

/11 CUDA 를 이용한 병렬 프로그래밍 DirectX 3D 를 이용한 3D 프로그래밍 2009. 7. 13.

Similar presentations


Presentation on theme: "/11 CUDA 를 이용한 병렬 프로그래밍 DirectX 3D 를 이용한 3D 프로그래밍 2009. 7. 13."— Presentation transcript:

1 /11 CUDA 를 이용한 병렬 프로그래밍 DirectX 3D 를 이용한 3D 프로그래밍 2009. 7. 13

2 /11 1.1 CUDA 를 사용한 Programming 의 장점 1  GPU 는 CPU 에 비해 ALU 의 수가 많다. 따라서, 작업을 동시에 처리할 수 있는 능력이 뛰어나다. 그렇기 때문에 GPU 에서 Program 이 실행되면, 반복적인 작업을 많이 처리하는 작업에서 월등한 성능향상을 기대할 수 있다.  GPU 에서 실행하는 Program 을 CUDA 를 이용하면 만들 수 있다.  또한 기존의 GPU Based Programming 과는 달리 CUDA 는 C 언어에 기본을 두고 있기 때문에, C 언 어 Programmer 가 쉽게 접근할 수 있다.  GPU 는 CPU 에 비해 ALU 의 수가 많다. 따라서, 작업을 동시에 처리할 수 있는 능력이 뛰어나다. 그렇기 때문에 GPU 에서 Program 이 실행되면, 반복적인 작업을 많이 처리하는 작업에서 월등한 성능향상을 기대할 수 있다.  GPU 에서 실행하는 Program 을 CUDA 를 이용하면 만들 수 있다.  또한 기존의 GPU Based Programming 과는 달리 CUDA 는 C 언어에 기본을 두고 있기 때문에, C 언 어 Programmer 가 쉽게 접근할 수 있다.

3 /11 1.2 CUDA 에서 Thread Hierarchy 2  Thread 는 Function 을 실행하는 기본 단 위이다. CUDA 에서는, function 을 몇 개 의 Thread 가 실행되게 할 것인지 정할 수 있다.  Thread 의 수는 Block 과 Grid 의 사이즈 를 정함으로써 정할 수 있다.  Thread 는 Block 내에 속해 있고, Block 은 Grid 에 속해 있다.  각 Block 과 Grid 는 최소 1 차원에서 최 대 4 차원까지의 Dimension 을 가질 수 있다.  Block 과 Grid 의 dimension 은 dim3 type 변수를 이용해 정의할 수 있다.  Thread 는 Function 을 실행하는 기본 단 위이다. CUDA 에서는, function 을 몇 개 의 Thread 가 실행되게 할 것인지 정할 수 있다.  Thread 의 수는 Block 과 Grid 의 사이즈 를 정함으로써 정할 수 있다.  Thread 는 Block 내에 속해 있고, Block 은 Grid 에 속해 있다.  각 Block 과 Grid 는 최소 1 차원에서 최 대 4 차원까지의 Dimension 을 가질 수 있다.  Block 과 Grid 의 dimension 은 dim3 type 변수를 이용해 정의할 수 있다.

4 /11 1.2 CUDA 에서 Thread Hierarchy – programming example 3  실제로 Programming 을 할 때 Thread 의 수를 정하는 것을 예제 코드로 보여주고 있다.  아래의 코드는 wgrd*hgrd 사이즈 Grid, wblk*hblk 사이즈 Block 만큼의 Thread 가 func 를 동시에 실 행하게끔 하는 코드이다.  규칙은 함수명 >> ( 파라메터 ); 이다.  실제로 Programming 을 할 때 Thread 의 수를 정하는 것을 예제 코드로 보여주고 있다.  아래의 코드는 wgrd*hgrd 사이즈 Grid, wblk*hblk 사이즈 Block 만큼의 Thread 가 func 를 동시에 실 행하게끔 하는 코드이다.  규칙은 함수명 >> ( 파라메터 ); 이다.

5 /11 1.3 CUDA 에서의 Function declaration(qualifier) 4  Function 을 declaration 할 때는 function 의 return type 앞에 __xxx__ 가 붙게 된다.  __xxx__ 를 이용해 function 이 실행되는 장치를 결정 내릴 수 있다.  __device__, __host__, __global__ 이렇게 세 가지가 있다.  Function 을 declaration 할 때는 function 의 return type 앞에 __xxx__ 가 붙게 된다.  __xxx__ 를 이용해 function 이 실행되는 장치를 결정 내릴 수 있다.  __device__, __host__, __global__ 이렇게 세 가지가 있다.  __device__ 장치내에서 실행되는 함수임을 의미한다. 또한, 이 함수는 장치내에서 실행되는 함수 안에서만 실 행될 수 있다.  __global__ 역시 장치내에서 실행되는 함수이다. 그러나 이 함수는 host 에서 실행되는 함수에서만 불려질 수 있다.  __host__ host 에서 실행되는 함수이며, host 에서 실행되는 함수에 의해서만 불려질 수 있다

6 /11 1.3 CUDA 에서의 Function declaration(qualifier) 5  Qualifier 에는 몇 가지 제한 사항이 있는데 정리하면 다음과 같다. __device__ 와 __global__ 은 재귀함수형식으로 사용될 수 없다. 또한, static variable 을 함수 내에 선언 할 수 없다. __global__ 함수는 void return type 를 가져야 한다.  Qualifier 에는 몇 가지 제한 사항이 있는데 정리하면 다음과 같다. __device__ 와 __global__ 은 재귀함수형식으로 사용될 수 없다. 또한, static variable 을 함수 내에 선언 할 수 없다. __global__ 함수는 void return type 를 가져야 한다.

7 /11 1.4 CUDA 에서의 Variable qualifier 6  Variable 에도 Qualifier 를 붙일 수 있다.  Qualifier 를 이용해 Variable 의 저장 위치를 정의할 수 있다.  Qualifier 에는 __device__, __constant__, __shared__ 이렇게 세 가지가 있다.  Variable 에도 Qualifier 를 붙일 수 있다.  Qualifier 를 이용해 Variable 의 저장 위치를 정의할 수 있다.  Qualifier 에는 __device__, __constant__, __shared__ 이렇게 세 가지가 있다.  __device__ global memory 에 저장되고, 프로그램이 살아있는 동안 지속되며, Grid 내의 모든 Thread 와 Host 에 서 접근이 가능하다.  __device__ constant memory 에 저장된다. 그 외의 성격은 __device__ 와 같다  __device__ Thread 가 속한 Block 내의 shared memory 에 저장된다. Block 이 소멸됨과 동시에 변수도 소멸된다. Block 내의 모든 Thread 가 참조 할 수 있다.

8 /11 1.5 CUDA 에서의 Memory Hierarchy 7  CUDA 에서의 Memory hierarchy 는 왼쪽 그 림과 같다.  Variable 을 선언할 때 variable 을 어느 memory 에 할당시키느냐에 따라 program 수행 속도가 차이가 나므로, 때에 따라 적 절한 memory 를 사용해야 한다.  CUDA 에서의 Memory hierarchy 는 왼쪽 그 림과 같다.  Variable 을 선언할 때 variable 을 어느 memory 에 할당시키느냐에 따라 program 수행 속도가 차이가 나므로, 때에 따라 적 절한 memory 를 사용해야 한다.

9 /11 1.6 CUDA 에서 Programming flow 8 1. CUDA 를 사용할 Device 를 초기화 시킨다.(Optional) 2. device 에서 사용할 포인터를 생성 3. cudaMalloc 을 이용해 장치내에 메모리를 잡는다. 4. host 에서 사용할 포인터를 생성 5. device 에서 필요한 값이 있으면, cudaMemcpy(d_p, h_p, size, cudaMemcpyHostToDevice); 6. device 에서 실행될 함수를 실행시켜 d_p 에 값을 채워넣음. 7. cudaMemcpy(h_p, d_p, size, cudaMemcpyDeviceToHost); 함수를 통해 device memory 에서 host memory 로 값을 받아옴. 1. CUDA 를 사용할 Device 를 초기화 시킨다.(Optional) 2. device 에서 사용할 포인터를 생성 3. cudaMalloc 을 이용해 장치내에 메모리를 잡는다. 4. host 에서 사용할 포인터를 생성 5. device 에서 필요한 값이 있으면, cudaMemcpy(d_p, h_p, size, cudaMemcpyHostToDevice); 6. device 에서 실행될 함수를 실행시켜 d_p 에 값을 채워넣음. 7. cudaMemcpy(h_p, d_p, size, cudaMemcpyDeviceToHost); 함수를 통해 device memory 에서 host memory 로 값을 받아옴.

10 /11 2.1 DirectX 3D 에 대해서 9  DirectX 3D 는 Microsoft 에서 만든 Graphic card device 를 제어할 수 있는 API 모음이다.  요즘은 Graphic Card 제조사도 다양하고, Chip 의 수도 다양하기 때문에, programmer 가 직접 device 를 제어하는 것은 사실상 불가능에 가깝기 때문에, DirectX 를 사용하면 효과적이다.  Application 과 Device 사이에는 Direct3D 와 HAL 이 존재해 Application 과 Device 를 연결해 준다.  HAL 은 Direct3D 조차 무수한 device 를 직접 control 하는 것은 불가능하기 때문에, HAL(Hardware Abstraction Layer) 가 존재해 Direct3D 와 Device 를 연계 시켜준다.  또한, 최신버전인 DirectX 10 보다 자료의 양이 더 많은 DirectX 9.0C 를 이용했다.  DirectX 3D 는 Microsoft 에서 만든 Graphic card device 를 제어할 수 있는 API 모음이다.  요즘은 Graphic Card 제조사도 다양하고, Chip 의 수도 다양하기 때문에, programmer 가 직접 device 를 제어하는 것은 사실상 불가능에 가깝기 때문에, DirectX 를 사용하면 효과적이다.  Application 과 Device 사이에는 Direct3D 와 HAL 이 존재해 Application 과 Device 를 연결해 준다.  HAL 은 Direct3D 조차 무수한 device 를 직접 control 하는 것은 불가능하기 때문에, HAL(Hardware Abstraction Layer) 가 존재해 Direct3D 와 Device 를 연계 시켜준다.  또한, 최신버전인 DirectX 10 보다 자료의 양이 더 많은 DirectX 9.0C 를 이용했다.

11 /11 2.2 Direct3D 초기화 10 Direct3D 를 사용하려면 먼저 장치를 초기화 해야한다. 1.IDirect3D9 인터페이스의 포인터를 얻는다. 2. 하드웨어 별로 지원 가능한 기능에 차이가 있기 때문에, 장치특성 (D3DCAPS9) 을 확인한 다. 3.IDirect3Ddevice9 인스턴스의 특성을 지정하기 위해 D3DPRESENT_PARAMETERS 구 조체 인스턴스를 초기화 한다. 4. 하드웨어 장치를 나타내는 C++ 객체인 IDirect3DDevice9 객체를 만든다. 1.IDirect3D9 인터페이스의 포인터를 얻는다. 2. 하드웨어 별로 지원 가능한 기능에 차이가 있기 때문에, 장치특성 (D3DCAPS9) 을 확인한 다. 3.IDirect3Ddevice9 인스턴스의 특성을 지정하기 위해 D3DPRESENT_PARAMETERS 구 조체 인스턴스를 초기화 한다. 4. 하드웨어 장치를 나타내는 C++ 객체인 IDirect3DDevice9 객체를 만든다.

12 /11 2.3 Framework 11  Direct3D 를 사용하면 거의 모든 프로그램이 같은 작업을 계속 해야 하므로, 이를 매번 코딩하는 것 은 상당히 소모적인 작업이다.  따라서, Framework 를 만들어 두면, 매 번 programming 할 때, 수고를 덜어 줄 수 있다.  d3dUtility.cpp/.h 에 각종 초기화 작업을 배치한다.  Main.cpp 에선 vertex 등을 생성하고, display 하는 함수와, WinMain 함수를 둔다.  Framework 은 Framework.zip 으로 압축해 두었다.  Direct3D 를 사용하면 거의 모든 프로그램이 같은 작업을 계속 해야 하므로, 이를 매번 코딩하는 것 은 상당히 소모적인 작업이다.  따라서, Framework 를 만들어 두면, 매 번 programming 할 때, 수고를 덜어 줄 수 있다.  d3dUtility.cpp/.h 에 각종 초기화 작업을 배치한다.  Main.cpp 에선 vertex 등을 생성하고, display 하는 함수와, WinMain 함수를 둔다.  Framework 은 Framework.zip 으로 압축해 두었다.

13 /11 2.4 Vertex 12  Direct3D 에서는 모든 Model 을 작은 삼각형 mesh 의 집합으로 표시한다. 이 때, mesh 의 꼭지점을 Vertex 라고 한다.  Direct3D 에서 Vertex 를 표현할 때, FVF(Flexible Vertex Format) 로 표현하게 된다. 즉, Vertex 의 구 성 성분을 직접 정의 할 수 있다.  Vertex 는 structure 로 구성성분을 정의 내릴 수 있다. 아래 예제 코드는 vertex 의 구성성분으로 공 간 좌표와 색으로 정의 되고 있다.  Direct3D 에서는 모든 Model 을 작은 삼각형 mesh 의 집합으로 표시한다. 이 때, mesh 의 꼭지점을 Vertex 라고 한다.  Direct3D 에서 Vertex 를 표현할 때, FVF(Flexible Vertex Format) 로 표현하게 된다. 즉, Vertex 의 구 성 성분을 직접 정의 할 수 있다.  Vertex 는 structure 로 구성성분을 정의 내릴 수 있다. 아래 예제 코드는 vertex 의 구성성분으로 공 간 좌표와 색으로 정의 되고 있다.

14 /11 2.5 Index 13  아래의 그림 처럼 D3D 에서 사각형을 만드려면, 삼각형 mesh 두 개가 필요하다.  이때 필요한 vertex 의 수는 각 삼각형 당 3 개씩이므로, 총 6 개가 필요하지만, 그림에서처럼 V0 와 V2 는 서로 겹쳐지므로, 총 필요한 Vertex 의 수는 4 개이다.  따라서, 중복되는 Vertex 2 개를 더 생성함으로써 메모리를 낭비하지 않기 위해, Index 를 사용한다.  즉, Index 는 Mesh 에 사용될 vertex 의 list 라고 볼 수 있다.  Ex) Vertex vertexList[4] = {v0, v1, v2, v3}; WORD indexList[6] = {0, 1, 2, // 좌측 삼각형 0, 2, 3}; // 우측 삼각형 이렇게 하게 되면, Vertex 에 비해 WORD 는 크기가 작으므로, Memory 를 아낄 수 있다.  아래의 그림 처럼 D3D 에서 사각형을 만드려면, 삼각형 mesh 두 개가 필요하다.  이때 필요한 vertex 의 수는 각 삼각형 당 3 개씩이므로, 총 6 개가 필요하지만, 그림에서처럼 V0 와 V2 는 서로 겹쳐지므로, 총 필요한 Vertex 의 수는 4 개이다.  따라서, 중복되는 Vertex 2 개를 더 생성함으로써 메모리를 낭비하지 않기 위해, Index 를 사용한다.  즉, Index 는 Mesh 에 사용될 vertex 의 list 라고 볼 수 있다.  Ex) Vertex vertexList[4] = {v0, v1, v2, v3}; WORD indexList[6] = {0, 1, 2, // 좌측 삼각형 0, 2, 3}; // 우측 삼각형 이렇게 하게 되면, Vertex 에 비해 WORD 는 크기가 작으므로, Memory 를 아낄 수 있다.

15 /11 2.6 가상 카메라 14  D3D 에서 Mesh 를 이용해 Model 을 여러 개 생성하면, 실제로 보여질 수 있는 model 이 있는가 하면, 없는 model 도 있다.  가상 카메라는 눈으로 보는 시점을 정의 내리며, 가상 카메라의 시야에 들어오지 않은 model 은 이 후 과정에서 처리되지 않는다.  가상 카메라는 사각뿔 모양으로 만들어지며, 수평, 수직 시야각과 투영윈도우, 가까운 평면, 먼 평 면으로 이루어 진다.  D3D 에서 Mesh 를 이용해 Model 을 여러 개 생성하면, 실제로 보여질 수 있는 model 이 있는가 하면, 없는 model 도 있다.  가상 카메라는 눈으로 보는 시점을 정의 내리며, 가상 카메라의 시야에 들어오지 않은 model 은 이 후 과정에서 처리되지 않는다.  가상 카메라는 사각뿔 모양으로 만들어지며, 수평, 수직 시야각과 투영윈도우, 가까운 평면, 먼 평 면으로 이루어 진다.

16 /11 2.7 Rendering Pipeline 15  D3D 에서 Vertex list 를 가지고 화면에 출력하는 과정은 아래와 같다. 아래와 같은 과정을 Rendering Pipeline 이라고 한다. 로컬 스페이스 -> 월드 스페이스 -> 뷰 스페이스 -> 후면 추려내기 -> 조명 -> 클리핑 -> 투영 -> 뷰포트 -> 래스터라이즈

17 /11 2.7.1 로컬스페이스 16  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스는 각 model 을 그리기 위한 스페이스이다.  우선 다른 model 들과의 상관관계를 고려하지 않고 자체의 좌표시 스템을 이용해 modeling 하는 공간이므로, 쉽고 단순하게 modeling 이 가능하다.  로컬스페이스는 각 model 을 그리기 위한 스페이스이다.  우선 다른 model 들과의 상관관계를 고려하지 않고 자체의 좌표시 스템을 이용해 modeling 하는 공간이므로, 쉽고 단순하게 modeling 이 가능하다.

18 /11 2.7.2 월드스페이스 17  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  월드스페이스는 여러 개의 model 들이 그려지는 공간이다.  로컬스페이스에서 modeling 된 model 들이 world space 에서 scene 을 이루게 된다.  Local space 에서 world space 로 변환될 때는 각 model 의 크기와 위 치, 방위각등이 결정된다.  World space 로의 변환은 하나의 model 을 변환할 때마다 각 model 의 상태를 결정해 줘야 하므로, model 당 한 번의 world space 변환을 하게 된다. 아래는 예제코드 ( 위치만 정의내림 )  월드변환을 한 번만 실행시키면, 동일 위치에 model 이 그려지게 된 다.  월드스페이스는 여러 개의 model 들이 그려지는 공간이다.  로컬스페이스에서 modeling 된 model 들이 world space 에서 scene 을 이루게 된다.  Local space 에서 world space 로 변환될 때는 각 model 의 크기와 위 치, 방위각등이 결정된다.  World space 로의 변환은 하나의 model 을 변환할 때마다 각 model 의 상태를 결정해 줘야 하므로, model 당 한 번의 world space 변환을 하게 된다. 아래는 예제코드 ( 위치만 정의내림 )  월드변환을 한 번만 실행시키면, 동일 위치에 model 이 그려지게 된 다.

19 /11 2.7.3 뷰스페이스 18  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  World Space 로 변환하고 나면, 물체의 위치등이 결정되고, 이 때 카 메라의 위치도 결정이 된다.  그러나 카메라의 위치가 임의의 좌표에 ( 원하는 위치더라도 ) 있다면 연산을 할 때 수월하지 않기 때문에, 카메라의 위치를 좌표계의 원 점에 위치시킬 필요가 있다. 이러한 과정을 뷰스페이스 변환이라고 하고, 카메라의 위치가 원점에 위치하고 방향을 +z 축을 향하게 둔 공간을 view space 라고 한다.  이렇게 view space 변환을 하게 되면, 카메라의 위치와 함께 모든 위 치가 같이 변해서, 결국 카메라로 보는 물체의 위치와 크기 방위각 등은 일정하게 된다. 아래는 view space 변환을 행할 행렬을 얻기 위 한 함수를 나타내며, 카메라의 위치와 보는 지점은 현재 위치와 보 는 지점이 된다.  위와 같은 함수를 통해 행렬을 얻으면 다음과 같은 함수를 통해 view space 변환을 실행할 수 있다.  World Space 로 변환하고 나면, 물체의 위치등이 결정되고, 이 때 카 메라의 위치도 결정이 된다.  그러나 카메라의 위치가 임의의 좌표에 ( 원하는 위치더라도 ) 있다면 연산을 할 때 수월하지 않기 때문에, 카메라의 위치를 좌표계의 원 점에 위치시킬 필요가 있다. 이러한 과정을 뷰스페이스 변환이라고 하고, 카메라의 위치가 원점에 위치하고 방향을 +z 축을 향하게 둔 공간을 view space 라고 한다.  이렇게 view space 변환을 하게 되면, 카메라의 위치와 함께 모든 위 치가 같이 변해서, 결국 카메라로 보는 물체의 위치와 크기 방위각 등은 일정하게 된다. 아래는 view space 변환을 행할 행렬을 얻기 위 한 함수를 나타내며, 카메라의 위치와 보는 지점은 현재 위치와 보 는 지점이 된다.  위와 같은 함수를 통해 행렬을 얻으면 다음과 같은 함수를 통해 view space 변환을 실행할 수 있다.

20 /11 2.7.4 후면추려내기, 조명, 클리핑 19  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  후면 추려내기란, 관찰점에서 앞면에 의해 가려진 뒷면을 이후 처리 과정에서 처리하지 않는 작업을 나타낸다. 이는 D3D 에 의해 자동으 로 처리되는 과정이다.  후면 추려내기에서 앞면은 view space 에서 시계방향으로 vertex 를 가진 polygon 을 앞면으로 취급하게 된다.  조명 역시 카메라처럼 원하는 위치의 월드스페이스 내에 정의 내릴 수 있으며, view space 변환 시 카메라와 마찬가지로 이동하게 된다.  클리핑은 카메라의 시점에 포함되지 않는 물체들을 추려내는 과정 을 말하며, 이 역시 D3D 에서 자동으로 처리된다.  후면 추려내기란, 관찰점에서 앞면에 의해 가려진 뒷면을 이후 처리 과정에서 처리하지 않는 작업을 나타낸다. 이는 D3D 에 의해 자동으 로 처리되는 과정이다.  후면 추려내기에서 앞면은 view space 에서 시계방향으로 vertex 를 가진 polygon 을 앞면으로 취급하게 된다.  조명 역시 카메라처럼 원하는 위치의 월드스페이스 내에 정의 내릴 수 있으며, view space 변환 시 카메라와 마찬가지로 이동하게 된다.  클리핑은 카메라의 시점에 포함되지 않는 물체들을 추려내는 과정 을 말하며, 이 역시 D3D 에서 자동으로 처리된다.

21 /11 2.7.5 투영 20  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  이 과정 까지 거치면, 컴퓨터의 시스템 내에서 3D 물체와 카메라, 조 명들이 모두다 결정이 됐다. 그러나 컴퓨터의 모니터는 2D 그래픽 을 표시하기 때문에, 3D 물체를 카메라의 시점에서 2D 그래픽화 하 는 과정이 남아 있으며, 이러한 과정을 투영이라고 한다.  투영은 원근 투영 (perspective projection) 을 이용하므로, 카메라의 정의에서 먼 평면에 있는 물체가 가장 작고, 가까운 평면에 있는 물 체가 가장 크게 그려지게 된다.  화면은 투영 윈도우에 맺히게 되는데, 앞서 view space 에서 카메라 를 +z 를 향하게 했으므로, 투영 윈도우는 +z 평면이고 z 의 값은 1 이 된다. 따라서 view space 에서 z < 1 인 model 은 나타나지 않는다.  아래는 투영 행렬을 만들고, 투영시키는 과정을 나타내는 코드를 나 타냈다.  이 과정 까지 거치면, 컴퓨터의 시스템 내에서 3D 물체와 카메라, 조 명들이 모두다 결정이 됐다. 그러나 컴퓨터의 모니터는 2D 그래픽 을 표시하기 때문에, 3D 물체를 카메라의 시점에서 2D 그래픽화 하 는 과정이 남아 있으며, 이러한 과정을 투영이라고 한다.  투영은 원근 투영 (perspective projection) 을 이용하므로, 카메라의 정의에서 먼 평면에 있는 물체가 가장 작고, 가까운 평면에 있는 물 체가 가장 크게 그려지게 된다.  화면은 투영 윈도우에 맺히게 되는데, 앞서 view space 에서 카메라 를 +z 를 향하게 했으므로, 투영 윈도우는 +z 평면이고 z 의 값은 1 이 된다. 따라서 view space 에서 z < 1 인 model 은 나타나지 않는다.  아래는 투영 행렬을 만들고, 투영시키는 과정을 나타내는 코드를 나 타냈다.

22 /11 2.7.6 Viewport 변환, 래스터라이즈 21  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  로컬스페이스  월드스페이스  뷰스페이스  후면추려내기  조명  클리핑  투영  뷰포트  래스터라이즈  Viewport 변환은 실제 display 될 화면의 영역을 지정하는 과정이다.  Windows application 의 경우 windows mode 에서 display 를 하게 될 경우 client 영역에서만 화면이 그려질 수 있고, 원하는 경우에는 client 영역에서도 작은 사각형 영역에만 그릴 수도 있다. 이러한 경 우에 필요한 과정이 viewport 변환이며, 전체화면 display 에 경우 이 과정은 생략할 수 있다.  이전까지의 과정에선 polygon 의 색이 결정돼 있지 않지만, 래스터 라이즈 과정을 거치면서 비로서 각 mesh 의 색이 결정되게 된다.  여기까지의 과정이 모두 완료되면, 비로서 화면에 display 가 된다.  Viewport 변환은 실제 display 될 화면의 영역을 지정하는 과정이다.  Windows application 의 경우 windows mode 에서 display 를 하게 될 경우 client 영역에서만 화면이 그려질 수 있고, 원하는 경우에는 client 영역에서도 작은 사각형 영역에만 그릴 수도 있다. 이러한 경 우에 필요한 과정이 viewport 변환이며, 전체화면 display 에 경우 이 과정은 생략할 수 있다.  이전까지의 과정에선 polygon 의 색이 결정돼 있지 않지만, 래스터 라이즈 과정을 거치면서 비로서 각 mesh 의 색이 결정되게 된다.  여기까지의 과정이 모두 완료되면, 비로서 화면에 display 가 된다.

23 /11 2.8 Vertex Buffer 와 Index Buffer 22  앞서 vertex 와 index 에 대해서 배웠다. 그러나 이 들을 array 로 저장하게 되면, system memory 에 저장되므로, rendering 에 시간지연이 생기므로, 이를 buffer 에 저장해 device memory 에 저장하게 된다.  좌측의 코드는 VertexBuffer 와 IndexBuffer 를 만 드는 함수이다.  Length – 버퍼에 할당할 바이트 수  Usage – 버퍼가 이용되는 방법을 결정한다. 보통 0 을 지정  FVF – Vertex 의 Format  Pool – 버퍼가 위치할 메모리 풀  ppVertexBuffer - - 만들어질 Vertex Buffer 를 받을 포인터  pSharedHandle – 이용되지 않음. 0 으로 지정  Format – 인덱스의 크기를 지정 D3DFMT_INDEX16 또는 D3DFMT_INDEX32 를 이용하는데 장치의 지원 여부에 따라 결 정  ppIndexBuffer – 만들어질 index buffer 를 받을 포인터  앞서 vertex 와 index 에 대해서 배웠다. 그러나 이 들을 array 로 저장하게 되면, system memory 에 저장되므로, rendering 에 시간지연이 생기므로, 이를 buffer 에 저장해 device memory 에 저장하게 된다.  좌측의 코드는 VertexBuffer 와 IndexBuffer 를 만 드는 함수이다.  Length – 버퍼에 할당할 바이트 수  Usage – 버퍼가 이용되는 방법을 결정한다. 보통 0 을 지정  FVF – Vertex 의 Format  Pool – 버퍼가 위치할 메모리 풀  ppVertexBuffer - - 만들어질 Vertex Buffer 를 받을 포인터  pSharedHandle – 이용되지 않음. 0 으로 지정  Format – 인덱스의 크기를 지정 D3DFMT_INDEX16 또는 D3DFMT_INDEX32 를 이용하는데 장치의 지원 여부에 따라 결 정  ppIndexBuffer – 만들어질 index buffer 를 받을 포인터

24 /11 2.9 버퍼 메모리에 접근 23  만들어진 buffer 에 접근하기 위해서는 Lock 함수를 사용해서 buffer 를 잠궈야 하고, 접근 후에는 반 드시 Unlock 을 시켜야 한다. IndexBuffer 도 사용법이 비슷하므로, VertexBuffer 에 대해서만 정리하 겠다.  Lock 을 수행한 후에는, ppbData 를 이용해 vertex 의 값을 쓰면 된다.  만들어진 buffer 에 접근하기 위해서는 Lock 함수를 사용해서 buffer 를 잠궈야 하고, 접근 후에는 반 드시 Unlock 을 시켜야 한다. IndexBuffer 도 사용법이 비슷하므로, VertexBuffer 에 대해서만 정리하 겠다.  Lock 을 수행한 후에는, ppbData 를 이용해 vertex 의 값을 쓰면 된다.

25 /11 2.10 드로잉 준비 24  우선 Stream source 를 지정해야 한다. Stream Source 를 Vertex Buffer 와 연결하여 rendering pipeline 에 buffer 를 보낼 수 있게 하는 작업이다.  그 다음 Vertex 의 Format 을 지정해야 한다. 앞서 vertex 는 FVF 이므로, 프로그래머가 정의하기에 따라 vertex 의 format 이 달라지므로, device 에 format 을 알려줘야 한다.  그 다음 index buffer 를 지정해야 한다. 이로써 모든 준비과정이 완료됐다.  우선 Stream source 를 지정해야 한다. Stream Source 를 Vertex Buffer 와 연결하여 rendering pipeline 에 buffer 를 보낼 수 있게 하는 작업이다.  그 다음 Vertex 의 Format 을 지정해야 한다. 앞서 vertex 는 FVF 이므로, 프로그래머가 정의하기에 따라 vertex 의 format 이 달라지므로, device 에 format 을 알려줘야 한다.  그 다음 index buffer 를 지정해야 한다. 이로써 모든 준비과정이 완료됐다.

26 /11 2.11 드로잉 25  드로잉을 시작할 때는 device 에 장면의 시작을 알려야 하고, 마친 후에는 장면의 끝을 알려줘야 한 다.  앞서 정의한 Index 를 이용해 그리는 함수  드로잉을 시작할 때는 device 에 장면의 시작을 알려야 하고, 마친 후에는 장면의 끝을 알려줘야 한 다.  앞서 정의한 Index 를 이용해 그리는 함수

27 /11 2.6 프로그램 구조 26  전역 변수로 IDirect3DDevice9*, IDirect3DVertexBuffer9*, IDirect3DIndexBuffer9*, int Width, int Height 를 선언한다.  Vertex 의 구조체를 정의한다.  Setup 함수에서는 Vertex buffer 와 Index buffer 를 생성하고, buffer 내에 vertex 와 index 정보를 채워 넣는다. 그리고, 카메라의 위치와 방향을 정하고, 투영행렬을 지정한다.  Display 함수에서는 그림을 출력시키고, 필요하다면 물체의 회전 등을 월드변환 또는 뷰스페이스 변환을 통해 미리 변환시킨다.  마지막으로 Cleanup 함수에서는 ib 와 vb 를 해제시킨다. Ex> d3d::Release ( 버퍼 );  전역 변수로 IDirect3DDevice9*, IDirect3DVertexBuffer9*, IDirect3DIndexBuffer9*, int Width, int Height 를 선언한다.  Vertex 의 구조체를 정의한다.  Setup 함수에서는 Vertex buffer 와 Index buffer 를 생성하고, buffer 내에 vertex 와 index 정보를 채워 넣는다. 그리고, 카메라의 위치와 방향을 정하고, 투영행렬을 지정한다.  Display 함수에서는 그림을 출력시키고, 필요하다면 물체의 회전 등을 월드변환 또는 뷰스페이스 변환을 통해 미리 변환시킨다.  마지막으로 Cleanup 함수에서는 ib 와 vb 를 해제시킨다. Ex> d3d::Release ( 버퍼 );


Download ppt "/11 CUDA 를 이용한 병렬 프로그래밍 DirectX 3D 를 이용한 3D 프로그래밍 2009. 7. 13."

Similar presentations


Ads by Google