언어/기타
2007.03.31 23:45

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

조회 수 1281 추천 수 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
번호 분류 제목 글쓴이 날짜 조회 수
1004 언어/기타 목에 좋은것들.... 1 켄타 2005.05.17 2070
1003 RPG Maker 좌표대입(ARPG) 사고실험.[이론편] 늑대소년 2005.05.18 1509
1002 언어/기타 스킬데미지를 10000이상 뜨게해보자.(턴알,액알 둘다) Dship 2005.05.18 1888
1001 언어/기타 Fruity Loops에서 FX탭 사용방법 (1) Mr^Lee 2005.05.18 1709
1000 RPG Maker RPG XP 배워보기 <변수를 마스터하자 상편> 1 덩키동크 2005.05.18 2205
999 언어/기타 100%고수강의!(변수이론) 늑대소년 2005.05.18 2470
998 언어/기타 나름대로 - 변수강좌 켈리시 2005.05.18 1624
997 언어/기타 변수(變數)의 기초 바람을 가르는 자 2005.05.19 1270
996 언어/기타 이번에는 오프닝을! 장아찌 2005.05.20 2635
995 RPG Maker 액션RPG 속성무기를 만들어보자!! 천룡수 2005.05.20 1538
994 RPG Maker 아르바이트를 만들자 . - 1 Norid 2005.05.20 1739
993 언어/기타 플레이어가 자기의 이름을 정한다 . [영어] file Norid 2005.05.21 1780
992 언어/기타 레벨업을 하라 . 그리하면 살것이니.. 1 file Norid 2005.05.22 1574
991 [RPG2000] 가이드북 -7- 창조도시 2005.05.22 11106
990 언어/기타 나라의 PHP 초보탈출 - 1편 나라 2005.05.22 1732
989 RPG Maker 경영 RPG만들기[콤플리트판] 늑대소년 2005.05.24 2039
988 [RPG2000] 가이드북 -1- (표지내용무) 창조도시 2005.05.25 14508
987 언어/기타 [c++] 생성자,파괴자 챔피온 2005.05.26 1668
986 언어/기타 《완벽하게 현실적인 게임을 만들려면 해야되는 조작 몇 가지》-[上편] 자이크로 2005.05.27 1852
985 언어/기타 [R2000] 초간단 단거리액알 2 비밀소년 2005.05.27 2521
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 51 Next
/ 51


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

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