我正在尝试使用灵活的几何实例代码来处理具有多种材质的网格。对于具有一种材料的网格,一切都很好。我设法通过一次绘制调用渲染尽可能多的实例。
多种材料使事情变得复杂一些。我的网格来自.x文件。它有一个顶点缓冲区,一个索引缓冲区但有几种材质。为每个子集(材质)呈现的索引存储在属性数组中。
以下是我使用的代码:
d3ddev->SetVertexDeclaration( m_vertexDeclaration );
d3ddev->SetIndices( m_indexBuffer );
d3ddev->SetStreamSourceFreq(0, (D3DSTREAMSOURCE_INDEXEDDATA | m_numInstancesToDraw ));
d3ddev->SetStreamSource(0, m_vertexBuffer, 0, D3DXGetDeclVertexSize( m_geometryElements, 0 ) );
d3ddev->SetStreamSourceFreq(1, (D3DSTREAMSOURCE_INSTANCEDATA | 1ul));
d3ddev->SetStreamSource(1, m_instanceBuffer, 0, D3DXGetDeclVertexSize( m_instanceElements, 1 ) );
m_effect->Begin(NULL, NULL); // begin using the effect
m_effect->BeginPass(0); // begin the pass
for( DWORD i = 0; i < m_numMaterials; ++i ) // loop through each subset.
{
d3ddev->SetMaterial(&m_materials[i]); // set the material for the subset
if(m_textures[i] != NULL)
{
d3ddev->SetTexture( 0, m_textures[i] );
}
d3ddev->DrawIndexedPrimitive(
D3DPT_TRIANGLELIST, // Type
0, // BaseVertexIndex
m_attributes[i].VertexStart, // MinIndex
m_attributes[i].VertexCount, // NumVertices
m_attributes[i].FaceStart * 3, // StartIndex
m_attributes[i].FaceCount // PrimitiveCount
);
}
m_effect->EndPass();
m_effect->End();
d3ddev->SetStreamSourceFreq(0,1);
d3ddev->SetStreamSourceFreq(1,1);
此代码仅适用于第一种材料。当我说第一个时我指的是索引0处的那个,因为如果我用第二个材质开始我的循环,它将不会被渲染。但是,通过调试PIX中的顶点缓冲区,我可以看到所有材料都正确处理。所以在顶点着色器之后会发生一些事情。
另一个奇怪的问题是,如果我将包含实例数据的流源设置为顶点大小为零,则将呈现我的所有材质。
所以不要这样:
d3ddev->SetStreamSource(1, m_instanceBuffer, 0, D3DXGetDeclVertexSize( m_instanceElements, 1 ) );
我将其替换为:
d3ddev->SetStreamSource(1, m_instanceBuffer, 0, 0 );
但是,当然,使用此代码,我的所有实例都呈现在相同的位置,因为我一遍又一遍地重复使用相同的实例数据。
最后一点,如果我使用D3DCREATE_SOFTWARE_VERTEXPROCESSING创建我的设备,一切正常。只有硬件有问题,但遗憾的是DirectX在调试模式下没有报告任何问题。
答案 0 :(得分:0)
如果要在硬件中实现着色器,则不能将vs_3_0或ps_3_0与任何其他着色器版本一起使用,并且您不能将任何着色器类型与固定功能管道一起使用。这些更改可以简化驱动程序和运行时。唯一的例外是只有软件的vs_3_0着色器可以与任何像素着色器版本一起使用。
答案 1 :(得分:0)
我有同样的问题,在我的情况下,问题是池实例化网格。我最初在SYSTEM_MEMORY中有这个网格,但在POOL_DEFAULT中有实例网格。当我将实例化网格物体更改为默认存储器时,一切都按预期工作。
希望它有所帮助。