如何使用D3DPT_TRIANGLESTRIP基元类型在DirectX中绘制两个分离的矩形

时间:2009-08-28 05:29:43

标签: c++ graphics directx direct3d

我是DirectX的新手,我正在尝试使用D3DPT_TRIANGLESTRIP在一个场景中绘制两个矩形。一个矩形没有问题,但两个矩形是一个完全不同的球类游戏。是的我可以使用用D3DPT_TRIANGLELIST基元类型绘制的四个三角形来绘制它们。我的好奇心在于使用D3DPT_TRIANGLESTRIP所涉及的技术。 我使用D3DPT_TRIANGLESTRIP为一个矩形使用的部分代码如下:

CUSTOMVERTEX recVertex[] = {
    {  10.0f,  10.0f, 0.10f, 1.0f, 0xffffffff, }, // x, y, z, rhw, color
    { 220.0f,  10.0f, 0.10f, 1.0f, 0xffffffff, },   
    {  10.0f, 440.0f, 0.10f, 1.0f, 0xffffffff, },   
    { 220.0f, 440.0f, 0.10f, 1.0f, 0xffffffff, },
}; 

if( FAILED( g_pd3dDevice->CreateVertexBuffer( 4 * sizeof( CUSTOMVERTEX ),
               0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
{
    return E_FAIL;
}

更重要的代码......

VOID* precVertex;    
if( FAILED( g_pVB->Lock( 0, sizeof( recVertex ), ( void** )&pGameField, 0 ) ) ) 
{
return E_FAIL; 
}
 memcpy( precVertex, recVertex, sizeof( recVertex ) );

然后像这样渲染...

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

基于这个模型,我可以轻松复制代码,更改自定义顶点上的x和y值,并创建另一个顶点缓冲区,它可以工作。

就个人而言,我觉得这不是最好的方式,特别是考虑到我必须画100个矩形或类似的情况。问题是,我没有其他想法。所以我的问题是,用D3DPT_TRIANGLESTRIP绘制两个矩形的最有效方法是什么?还有一种可能的方法来复制和转换当前的矩形吗?

4 个答案:

答案 0 :(得分:3)

最有效的方法是使用索引绘制,然后在2个矩形之间重复索引。

即索引0,1,2,3,3,4,4,5,6,7从三角形剥离中产生以下三角形

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

三角形2,3,3,3,3,4,4,4,4和4,5都具有零面积并且将在图形卡上很早地丢弃。这样,您可以在一次调用DrawIndexedPrimitive时获得4个三角形。

当然,这意味着你要发送10个指数。您也可以只发送12个索引并在三个列表中将两个矩形绘制为4个三角形。使用索引绘图时,您会发现硬件会跟踪它已经转换过的顶点,这样就不必再费心了。

即如果将索引缓冲区定义为

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

并且你有一个至少4个顶点的后变换缓存(几乎每个显卡都有一个明显更大的后变换缓存,GeForce 3肯定会!)然后你可以看到两个三角形都将被渲染,但每个顶点只会改变一次。在直观的任何DX8后硬件(即任何DX9或10硬件)上,您会发现使用此帖子转换缓存和三角形列表的额外简单性意味着您将从三角形列表中获得比三角形更好的性能条。

总而言之,回答问题“所以我的问题是,用D3DPT_TRIANGLESTRIP绘制两个矩形的最有效方法是什么?”答案是绘制D3DPT_TRIANGLELIST并且不再担心它:)

答案 1 :(得分:1)

将第二个矩形的四个顶点添加到顶点缓冲区,然后两次调用DrawPrimitive

g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX ) );
g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 4, 2 );

答案 2 :(得分:1)

您可以将recVertex扩展到8分。这是一种常见的技术。 3D硬件设计为完全在这种模式下工作。例如,查看this教程。

如果你想绘制100(我认为在问题的上下文中意味着“一个巨大的数字”)矩形,你应该考虑使用meshes

答案 3 :(得分:0)

通常最好将几何体批量化为较大的索引顶点缓冲区,并使用正确的偏移调用适当的绘制函数到每个3D对象的缓冲区中。记住硬件不会将对象视为单独的实体,它只关心顶点/索引缓冲区,纹理,着色器程序和各种状态。您的工作是以最佳方式将所有内容提供给硬件,并每帧批量处理合理数量的绘图任务。

对于像这样的微小几何和固定功能,你绝对应该把整个拍打到一个缓冲区。