您当前的位置: 首页 >  3d

鱼儿-1226

暂无认证

  • 0浏览

    0关注

    1100博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Direct3D研究院之使用索引缓冲区绘制图形(四)

鱼儿-1226 发布时间:2020-08-18 11:37:18 ,浏览量:0

有些复杂的图形是由多个相邻的三角形拼接而成的,比如5、6边形等,假如为每个三角形分配3个顶点,但是这样就会出现顶点相互重合的情况,从而造成内存的浪费,显然这是得不偿失的。那有没有更合适的处理方式呢?当然,索引缓冲区可以很好解决这个问题。

索引缓冲区和顶点缓冲区一样,都是COM接口,它其中保存的是多边形的三角形顶点在顶点缓冲区的索引,程序需要做的就是设置三角形的组合,然后通过各种顶点的组合绘制出复杂图形,这样就避免了重复顶点的出现,它的数值最多就是一个16或32位的整数,这要比一个顶点所占用的内存小得多。因此在绘制那些顶点重复使用较多的复杂图形时,用索引缓冲区绘制效果好得多。

下面,我们就利用索引缓冲区绘制一个正多边形(此项目基于上一章内容)。

首先声明索引缓冲区指针对象:

C#

1

LPDIRECT3DINDEXBUFFER9 g_pIB = NULL;

然后,修改InitVB方法:

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

HRESULT InitVB()

{

//创建顶点缓冲区

VERTEX vertexes[LINE_NUM + 1];

vertexes[0].x = POSITION_X;

vertexes[0].y = POSITION_Y;

vertexes[0].z = 1.0f;

vertexes[0].rhw = 1.0f;

vertexes[0].color = 0xffffffff;

 

for (int index = 0; index < LINE_NUM; ++index)

{

vertexes[index + 1].x = (float)(RADIUS * sin(index * 2 * PI / LINE_NUM)) + POSITION_X;

vertexes[index + 1].y = -(float)(RADIUS * cos(index * 2 * PI / LINE_NUM)) + POSITION_Y;

vertexes[index + 1].z = 1.0f;

vertexes[index + 1].rhw = 1.0f;

vertexes[index + 1].color = 0xffabcdef;

}

 

if (FAILED(g_pDevice->CreateVertexBuffer( sizeof(vertexes)

, 0

, FVF

, D3DPOOL_DEFAULT

, &g_pVB

, NULL )))

{

return E_FAIL;

}

 

void *pvertexes = NULL;

if (FAILED(g_pVB->Lock(0, sizeof(vertexes), (void**)&pvertexes, 0)))

{

return E_FAIL;

}

memcpy(pvertexes, vertexes, sizeof(vertexes));

g_pVB->Unlock();

 

//创建索引缓冲区

WORD indices[3 * LINE_NUM];

for (int index = 0; index < LINE_NUM; ++index)

{

indices[index * 3] = 0;

indices[(index * 3) + 1] = (index + 1) % (LINE_NUM + 1);

indices[(index * 3) + 2] = (index + 2) % (LINE_NUM + 1) + (index == LINE_NUM - 1 ? 1 : 0);

}

if (FAILED(g_pDevice->CreateIndexBuffer(sizeof(indices),

0,

D3DFMT_INDEX16,

D3DPOOL_DEFAULT,

&g_pIB,

NULL)))

{

return E_FAIL;

}

 

void *pIndices = NULL;

if (FAILED(g_pIB->Lock(0, sizeof(indices), (void**)&pIndices, 0)))

{

return E_FAIL;

}

memcpy(pIndices, indices, sizeof(indices));

g_pIB->Unlock();

return S_OK;

}

在InitVB方法中,我们修改了原来的顶点缓冲区,因为绘制的是正多边形,所以在填充顶点缓冲区时,使用了三角函数进行处理。初始化索引缓冲区大小时需要注意的是,索引缓冲区中的数据一定要可被3整除,因为我们是以三角形为单位绘制的。

其中CreateIndexBuffer方法创建了索引缓冲区,它有6个参数,第一个参数表示创建的索引缓冲区的大小(以字节为单位);第二个参数表示索引缓冲区的属性,此处取默认值0;第三个参数为索引缓冲区中数据的格式,这个有具体使用的数据为准,此处为16位数据;第四个参数为内存类型(D3DPOOL);第五个参数为索引缓冲区指针地址;第六个参数为保留参数,此处置为NULL。

在填充索引缓冲区时,和填充顶点缓冲区相同,都需要先加锁再解锁,以保证操作的安全。

接着是Render方法,

C#

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

void Render()

{

if (NULL == g_pDevice)

{

return;

}

 

g_pDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(30, 60, 90), 1.0f, 0);

 

if (SUCCEEDED(g_pDevice->BeginScene()))

{

g_pDevice->SetStreamSource(0, g_pVB, 0, sizeof(VERTEX));

g_pDevice->SetFVF(FVF);

g_pDevice->SetIndices(g_pIB);

g_pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, LINE_NUM + 1, 0, LINE_NUM);

g_pDevice->EndScene();

}

 

g_pDevice->Present(NULL, NULL, NULL, NULL);

}

在Render方法中主要增加了一个SetIndices方法,以及修改原来的绘制方法DrawPrimitive为DrawIndexedPrimitive。SetIndices方法只有一个参数,就是索引缓冲区指针。DrawIndexedPrimitive方法有6个参数,第一个参数是绘制的图元的类型,在此为三角形列表;第二个参数为索引缓冲区的起始地址,此处设置为0,表示从头开始绘制;第三个参数为索引缓冲区中最小的索引值;第四个参数为所要绘制的图形的顶点个数;第五个参数表示从索引缓冲区的哪个元素开始绘制;第六个参数绘制图元的数量。

最后,cleanup方法中添加索引缓冲区对象释放代码,

C#

1

2

3

4

if (NULL != g_pIB)

{

        g_pIB->Release();

}

运行程序,我们看到下面的效果,

关注
打赏
1604459285
查看更多评论
立即登录/注册

微信扫码登录

0.0463s