언어/기타
2007.03.31 23:45

[DX&C++] IndexBuffer를 알아보자!

조회 수 1240 추천 수 3 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄

 


 


 


* 이번에 올리는 글은 지난번 DX 튜토리얼 02 분석 예제를 잘 이해하신 분들만 이해가 되실 것입니다. *


 


 


 


오늘은 인덱스 버퍼라는 개념을 알아보는 시간입니다.


 


제가 만들고 있는 지형엔진에서도 인덱스 버퍼를 이용하여 지형을 렌더링 할 만큼, 최적화를 잘 할시에는 셰이더 못지 않는 성능을 발휘합니다.


 


그만큼 고정된 모델(Mesh)를 그리는데에는 발군의 성능을 자랑하니 잘 알아두셔야 합니다.


 


 


 


인덱스 버퍼란, 정의적으로 버텍스 버퍼의 인덱스만을 저장한 버퍼를 말합니다.


 


즉, 우리가 예제에서 사용하거나 직접작성한 버텍스 구조체 배열의 인덱스들을 저장한 또 다른 배열이라고 보면 되겠습니다.


 


 


 


지난시간에 FVF를 설정하여 고정파이프라인을 통해 렌더링을 구현하였습니다.


 


 


 


#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)


 


이와 같이 D3DFVF를 이용하여 구조체 특성을 적어주고,


 


 


struct CUSTOMVERTEX
{
    FLOAT x, y, z, rhw; // 버텍스의 위치
    DWORD color;        // 버텍스의 색
};


 


이러한 구조체를 이용하여 버텍스 특성을 적어주었던 기억이 나실것입니다.


 


 


 


이런 설정만 해주면 DX를 통해 3D 좌표연산이 '자동으로' 진행되는 방식을 '고정 파이프라인을 통과한다'고 말합니다.


 


 


 


 


 


지난번에는 단순한 삼각형을 그렸기때문에 단순히 버텍스 버퍼를 이용해 그림을 그리는 것의 비효율성을 느끼지 못하셨을 것입니다.


 


다음 육면체를 그리는데에 있어서 좌표 설정을 하는 부분을 살펴봅시다.


 


----------------------------------------------------------------------


    /* 우리가 그릴 육면체는 사각형 6개로 이루어진 입체 도형이다.


     * 하지만 3D 표현에서는 삼각형2개를 이용하여 사각형을 표현하므로,


     * 전체 12개의 삼각형에 대한 기술이 필요하다.


     */


 


    CUSTOMVERTEX g_Vertices[] = 
    {
                { -1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255,   0,   0, 0)}, // 0 
                { -1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 1 
                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 



                { -1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 1 
                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 


                {  1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255,   0, 255, 0)}, // 3


 


                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 


                {  1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255,   0, 255, 0)}, // 3
                {  1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 7 


 


                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 


                {  1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 7 
                {  1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(0  , 255, 255, 0)}, // 6


 


                { -1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 4 
                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 
                {  1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(0  , 255, 255, 0)}, // 6


 


                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 
                {  1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(0  , 255, 255, 0)}, // 6
                {  1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 7 


 


                { -1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255,   0,   0, 0)}, // 0 
                { -1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 1 
                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 


 


 


                { -1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255,   0,   0, 0)}, // 0 
                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 
                { -1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 4 


 


                { -1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255,   0,   0, 0)}, // 0 
                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 


                { -1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 4 


 


                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 


                { -1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 4 
                {  1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(0  , 255, 255, 0)}, // 6


 


                { -1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 1 
                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 
                {  1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255,   0, 255, 0)}, // 3

                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 
                {  1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255,   0, 255, 0)}, // 3
                {  1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 7 
    };


 


 


---------------------------------------------------------------------------------


 


후우.. 깁니다. 단순히 육면체를 그리기만 하는데에도 길이가 상당합니다.


 


하지만, 잘 살펴보시면, 똑같은 정점을 표현하는 부분이 많이 있음을 알 수 있을 것입니다. 오른쪽에 주석으로 번호를 달아두었지요?


 


해당 번호가 같은 부분은 완전히 같은 정점을 가리키는 부분입니다.


 


6면체에 존재하는 정점은 총 8개이지만, 3각형 2개를 그리기위해 1면당 2개의 정점이 중복으로 표현되는 것이지요.


 


이해가 가십니까?


 


 


1--------2


|          / |


|     /      |


|/           |


3--------4


 


이와 같은 사각형을 그리기 위해, (1,2,3) (2,3,4)의 정점이 필요한 것입니다.


 


이런 비 효율성을 극복하기 위해 나온것이 인덱스 버퍼입니다. 단순히 필요한 정점목록만 정의를 하고, 인덱스만 따로 정의하여 넣어주는 방식이지요.


 


 


 


 


    CUSTOMVERTEX g_Vertices[] =
    {
                { -1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255,   0,   0, 0)}, // 0 
                { -1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 1 
                {  1.0f, 1.0f, -1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 2 
                {  1.0f,-1.0f, -1.0f, D3DCOLOR_RGBA(255,   0, 255, 0)}, // 3
                { -1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 4 
                { -1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255, 255, 0)}, // 5 
                {  1.0f, 1.0f,  1.0f, D3DCOLOR_RGBA(0  , 255, 255, 0)}, // 6 
                {  1.0f,-1.0f,  1.0f, D3DCOLOR_RGBA(255, 255,   0, 0)}, // 7 
    };


    WORD g_Idx[] =
    {
                0,1,2,
                1,2,3,
                2,3,7,
                2,7,6,
                4,5,6,
                5,6,7,
                0,1,5,
                0,5,4,
                0,2,4,
                2,4,6,
                1,5,3,
                5,3,7 
     };


 


아까보다는 간결하게 되었습니다. 꼭 필요한 정점 8개를 선언하고, 16비트 인덱스를 사용할경우 WORD 배열에 해당 인덱스를 적어주기만 하면 되는 것이지요.


 


잘 살펴보시면, 맨 처음의 배열 선언의 순서와 완전히 같습니다. (주석의 번호와 비교해보세요.)


 


 


 


이 경우 버텍스 버퍼만을 사용한 것보다 더 빠른 렌더링이 가능하다고 알려져 있습니다.


 


 


 


하지만 nVidia 에서는 '자사의 그래픽카드에서는 TRIANGLE_STRIP을 사용하는 것이 더 빠른 구동이 가능하다'고 밝혔으므로, 그 방법을 통해 더 최적화를 해보도록 하겠습니다.


 


TRIANGLE_STRIP은 TRIANGLE_LIST와 버퍼 접근의 방식이 다릅니다.


 


TRIANGLE_LIST는 앞에서 3개씩 정점을 끊어 삼각형을 그리는 방식이고, TRIANGLE_STRIP은 최초 3개의 정점에서 정점정보 1개씩 읽어가며 그림을 그리는 방식입니다.


 


 


1--------2


|          / |


|     /      |


|/           |


3--------4


 


이와 같은 사각형을 그릴시에 TRIANGLE_LIST는


 


{


     1, 2, 3,


     2, 3, 4


}


 


라는 배열이 필요하지만, TRIANGLE_STRIP은


 


{


     1, 2, 3, 4
}


 


이것으로 끝입니다. 이후 그래픽카드는 [(1,2,3),4], [1,(2,3,4)] 식으로 3개씩 읽어들이는 방식이지요.


 


 


이것을 이용하여 육면체를 그리는데에는 좀 고민이 필요할 것입니다. (이것은 한붓 그리기 문제와 비슷합니다. ^^;;)


 


 


 


잘 고민을 해보시면, 다음과 같은 답을 얻으실 수 있습니다. (다른 답도 많습니다.)


 


0, 1, 2, 3, 6, 7, 4, 5, 0, 1, 1, 5, 3, 7, 7, 6, 6, 2, 4, 0


 


원래 36개의 인덱스를 이용해 그림을 그렸던 것을, 20개의 인덱스로 줄였습니다.


 


이때 011, 115, 377, 776, 766, 662 등은 화면에 보이지 않게 됩니다. (DX 루틴상 그림을 그리게되지만 모양상 화면에 드러나지 않습니다.)


 


 


 


사실 위의 결과는 완전히 최적화된 결과가 아닙니다. 더 개선할 여지가 많이 있는 인덱스 배치라는 말이지요.


(예제는 단순하게 직선으로 연결된 4면을 우선적으로 그린후, 양면을 채워넣은 방식입니다.)


 


자신만의 답을 구하신 분은 이 게시물 덧글에 답을 올려주시기 바랍니다. (강의 역사상 처음드리는 과제이지요?)


 


답은 여러가지가 있습니다. 버텍스 구조를 바꾸어도 되고, 인덱스 버퍼만 손을 보아도 좋습니다.


 


위의 답이 어떻게 나오게 되었는지를 고민해서 스스로 답을 구하신다면, 버텍스의 배치를 신중하게 정할 것이며, 더 좋은 퍼포먼스를 낼 수 있는 기반을 마련할 수 있을 것입니다.


 


 


 

?

List of Articles
번호 분류 제목 글쓴이 날짜 조회 수
844 언어/기타 렉없는 자동세이브 스크립트!!! 귀찮아‡ 2007.04.22 1474
843 언어/기타 [DX&C++] 3D를 넘어 2D로! Zeprod 2007.04.18 1675
842 언어/기타 코드진행 기초테크닉 1 나그네M 2007.04.14 709
841 언어/기타 그림 메뉴 2 [제 2의 타이틀 메뉴 (기본 메뉴편)] [거히 치트비법..] file 우드록맨 2007.04.12 771
840 RPG Maker 마우스 이동 스크립트 2 아크로s 2007.04.11 1965
839 언어/기타 '에피소드'형식이 아닌 '화' 형식의 시나리오는 어떨까요? 우드록맨 2007.04.09 1529
838 RPG Maker [초 노가다 시스템]그림 메뉴 1 file 우드록맨 2007.04.08 880
837 언어/기타 [DX&C++]3D공간상 카메라 시점의 대한 정의 실베 2007.04.02 1351
» 언어/기타 [DX&C++] IndexBuffer를 알아보자! Zeprod 2007.03.31 1240
835 언어/기타 3D좌표계에 3D물체를 찍기위환 기초과정 실베 2007.03.31 1355
834 언어/기타 [공개자료] 먼치킨 액알 만들기 책벌레공상가 2007.03.30 2499
833 언어/기타 [DX&C++] 3대 행렬 연산의 사용 Zeprod 2007.03.30 1404
832 언어/기타 숫자 게이지 색에 관한 팁 『덩키동크』 2007.03.30 1427
831 언어/기타 [DX&C++] 3D를 다루는 프로그램의 개요 Zeprod 2007.03.25 1247
830 언어/기타 template에 관한 간단한 예. 김두한 2007.03.12 1180
829 언어/기타 [고난도 시스템] 당구를 만들어 보자 5 SSS 2007.03.12 1197
828 언어/기타 2D격투게임만들기95 황금잉어빵 2007.03.08 2410
827 RPG Maker 1 - 1. 변수 응용 프로그램 만들기 (난수) 천영진 2007.03.06 1279
826 언어/기타 몬스터 성향 괴인X 2007.03.04 1256
825 언어/기타 [DX&C++] 3D 공간에 대한 이해 Zeprod 2007.03.04 1247
Board Pagination Prev 1 ... 4 5 6 7 8 9 10 11 12 13 ... 51 Next
/ 51






[개인정보취급방침] | [이용약관] | [제휴문의] | [후원창구] | [인디사이드연혁]

Copyright © 1999 - 2016 INdiSide.com/(주)씨엘쓰리디 All Rights Reserved.
인디사이드 운영자 : 천무(이지선) | kernys(김원배) | 사신지(김병국)