我一直在跟随一本关于D3D11游戏编程基础知识的书。我现在理解Direct3D的绝对基础:)
但......我有一个问题。 在书中,我总是不得不一次制作一个演示。现在,我正在尝试用它制作2D游戏。因为我不想习惯坏习惯,所以我需要你的建议。
在本书中,我总是要定义一个(带有texcoord和位置成员的结构VertexPos)或(只有一个XMFLOAT3位置成员的结构VertexPos)。在我正在制作的游戏中,我希望能够绘制没有纹理的固体表面和具有纹理的表面。我不知道如何做到这一点,更不用说有效地做到这一点。
这是我的渲染功能:
void GameSpriteDemo::Render()
{
if (m_pD3DContext == 0)
{return;}
float ClearColor[4] = {0.0f, 0.0f, 0.25f, 1.0f};
m_pD3DContext->ClearRenderTargetView(m_pBackBufferTarget,ClearColor);
UINT stride = sizeof(VertexPos);
UINT offset = 0;
m_pD3DContext->IASetInputLayout(m_pInputLayout);
m_pD3DContext->IASetVertexBuffers(0,1,&m_pVertexBuffer, &stride, &offset);
m_pD3DContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_pD3DContext->VSSetShader(m_pSolidColorVS,0,0);
m_pD3DContext->PSSetShader(m_pSolidColorPS,0,0);
m_pD3DContext->PSSetShaderResources(0,1,&m_pColorMap);
m_pD3DContext->PSSetSamplers(0,1,&m_pColorMapSampler);
for(int i=0; i < 2; ++i)
{
XMMATRIX world = m_Sprites[i].GetWorldMatrix();
XMMATRIX mvp = XMMatrixMultiply( world, m_VpMatrix );
mvp = XMMatrixTranspose(mvp);
m_pD3DContext->UpdateSubresource(m_pMvpCB,0,0,&mvp,0,0);
m_pD3DContext->VSSetConstantBuffers(0,1,&m_pMvpCB);
m_pD3DContext->Draw(6,0);
}
m_pSwapChain->Present(0,0);
}
那么,我应该如何有效地处理多个顶点缓冲区,输入布局,着色器,搅拌器等?
我应该只创建那些版本的多个版本,然后在Draw调用之后设置重置输入程序集,着色器等吗?或者这不起作用/这效率不高吗?
谢谢:)
答案 0 :(得分:4)
简单的答案是肯定的,您应该创建多个顶点缓冲区,输入布局,着色器等,并在每个相应的绘制调用之前设置适当的顶点缓冲区。这将起作用并且相当有效(对于现代硬件上的2D游戏应该足够有效)。
在完整的3D游戏引擎中,事情往往变得复杂一些。通常,渲染引擎将在原始对象(如顶点和索引缓冲区,输入布局,着色器等)之上分层设置一些额外的内部抽象级别。
构造事物的一种相当常见的简单方法是使用一个Mesh类来了解所有顶点缓冲区,索引缓冲区,输入布局,着色器,纹理等,它们构成了一个可以成为3D模型的东西。在单个绘制调用中绘制并负责将它们全部设置(通常与渲染状态的其他位一样,如混合模式,剔除模式等)并发出相应的绘制调用。
与更改任何设备状态相关的成本因此,渲染引擎通常被设计为尝试对需要在特定帧中绘制的所有对象进行排序,以便最小化所需的状态更改的数量。例如,在Dawn of War 2渲染器中,我们对所有网格几何进行了排序,以便我们可以绘制例如在绘制具有不同顶点和索引缓冲区,纹理等的所有太空海洋体之前,所有需要最小状态变化的太空船头盔。
现代3D硬件和API在改变状态方面的开销比过去少一些,因此排序以最小化状态变化比以前更不重要但是对于需要获得最大性能的游戏来说仍然是常见的做法。 PC。
在数据驱动的渲染引擎中,支持灵活的光照和材质模型以及蒙皮动画,地形,粒子系统,全屏效果,2D UI等,是管理游戏所需的所有状态的合适设计对象和对它进行排序以便以最高效率绘制它可以变得非常复杂,并且有许多不同的方法来构造事物。可归类为“渲染器状态管理”的所有内容的代码通常构成典型渲染引擎中代码的重要部分。