언어/기타
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
번호 분류 제목 글쓴이 날짜 조회 수
744 RPG Maker RPG게임만들때 필요한 [ Tip ] 사토루 2005.08.08 1275
743 언어/기타 원의 방정식 알고리즘 file Spegel 2006.09.17 1272
742 언어/기타 약간의 아이디어.. 닉네임군 2006.10.08 1264
741 언어/기타 비밀번호를 설정해서 다른사람이 못하도록 만들어보자. 야미토츠바사 2005.08.29 1263
740 언어/기타 델파이를 이용한 게임 제작? 리닥터즈 2007.01.26 1262
739 언어/기타 몬스터 성향 괴인X 2007.03.04 1256
738 언어/기타 맵배치? 마스터! [집] -H- 2006.06.19 1254
737 RPG Maker RPG XP 배워보기 <직접제작메뉴예제> file 덩키동크 2005.11.12 1253
736 언어/기타 [DX&C++] 3D를 다루는 프로그램의 개요 Zeprod 2007.03.25 1247
735 언어/기타 [DX&C++] 3D 공간에 대한 이해 Zeprod 2007.03.04 1247
734 언어/기타 인공지능 동료를 만들어보자!! 다크세이버™ 2006.06.07 1240
» 언어/기타 [DX&C++] IndexBuffer를 알아보자! Zeprod 2007.03.31 1240
732 언어/기타 변수(變數)의 기초 바람을 가르는 자 2005.05.19 1235
731 RPG Maker 알툴 2k 에서의 SRPG 구현에 대한 고민 1 하로우 2006.03.19 1226
730 언어/기타 [연구] 신개념 액알, 노가다를 최소한으로? SSS 2007.01.29 1225
729 언어/기타 BGM과 ME가 재생이 안될때 View2er 2007.01.16 1223
728 RPG Maker RPG2K 최적화 백과 사전 7 아싸사랑 2010.07.12 1220
727 언어/기타 [이벤트 ID이용의 예]슈팅 게임 file masa 2006.12.16 1215
726 RPG Maker 범위를 구할때 쓸 수 있는 식 둘 메카_탁 2006.12.09 1214
725 언어/기타 스토리아이디어 B HERO 2006.10.22 1212
Board Pagination Prev 1 ... 9 10 11 12 13 14 15 16 17 18 ... 51 Next
/ 51






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

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