0

ゲーム「マインクラフト」風のプロジェクトで働いています。

同一のモデルを持つキューブを多数生成するために、「モデルのインスタンス化」を使い始めました。ここまでは順調ですね。私の問題は、行列のサイズを[500-1-500] ( 250,000 立方メートル) の [300-1-300] ( 90,000 立方メートル) から描画するように大きくすると、プログラムの速度が大幅に低下することです。60fpsから20fpsに…

理由がよくわかりません。しかし、私は「ハードウェアのインスタンス化」という手法を正しく使用しています。また、フォーラムで、この手法により XNA で最大 700 万立方体を描画できることにも気付きました!! 私の問題がどこから来たのか分かりますか?

どうもありがとうございます

インスタンス化されたモデルを描画する関数は次のとおりです。

// Draw the 3D map (world) of game 
public void drawWorld(GameTime gameTime)
{
    / * Draw all the structures that make up the world with the instancing system * /
    Array.Resize(ref instanceTransforms, smallListInstance.Count);

    for (int i = 0; i < ListInstance.Count; i++)
    {
        instanceTransforms[i] = ListInstance[i].Transform;
    }

    DrawModelHardwareInstancing(myModel, myTexture2D,instancedModelBones,instanceTransforms, arcadia.camera.View, arcadia.camera.Projection);


}
// ### end function drawWorld

これは、マイクロソフトのサンプルで使用されているメソッド[Hardware Instancing]でモデルを描画する関数 [DrawModelHardwareInstancing]です。

// Function that will draw all the models instantiated in the list
void DrawModelHardwareInstancing(Model model,Texture2D texture, Matrix[] modelBones,
                                 Matrix[] instances, Matrix view, Matrix projection)
{
    Game.GraphicsDevice.SamplerStates[0] = SamplerState.LinearWrap;
    if (instances.Length == 0)
        return;

    // If we have more instances than room in our vertex buffer, grow it to the neccessary size.
    if ((instanceVertexBuffer == null) ||
        (instances.Length > instanceVertexBuffer.VertexCount))
    {
        if (instanceVertexBuffer != null)
            instanceVertexBuffer.Dispose();

        instanceVertexBuffer = new DynamicVertexBuffer(Game.GraphicsDevice, instanceVertexDeclaration,
                                                       instances.Length, BufferUsage.WriteOnly);
    }

    // Transfer the latest instance transform matrices into the instanceVertexBuffer.
    instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);

    foreach (ModelMesh mesh in model.Meshes)
    {
        foreach (ModelMeshPart meshPart in mesh.MeshParts)
        {
            // Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
            Game.GraphicsDevice.SetVertexBuffers(
                new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
                new VertexBufferBinding(instanceVertexBuffer, 0, 1)
            );

            Game.GraphicsDevice.Indices = meshPart.IndexBuffer;


            // Set up the instance rendering effect.
            Effect effect = meshPart.Effect;
            //effect.CurrentTechnique = effect.Techniques["HardwareInstancing"];
            effect.Parameters["World"].SetValue(modelBones[mesh.ParentBone.Index]);
            effect.Parameters["View"].SetValue(view);
            effect.Parameters["Projection"].SetValue(projection);
            effect.Parameters["Texture"].SetValue(texture);


            // Draw all the instance copies in a single call.
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();

                Game.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0,
                                                       meshPart.NumVertices, meshPart.StartIndex,
                                                       meshPart.PrimitiveCount, instances.Length);
            }
        }



    }
}
// ### end function DrawModelHardwareInstancing
4

1 に答える 1

0

どうもありがとうございました!あなたのアドバイスのおかげで、私は最終的に私の問題を解決しました;-)!

私は自分の視野「カメラ」の前にあるモデルだけを描きます。「編集」、「新しい位置など..」が必要な場合にのみモデルを更新します。

私の最後のステップは、パフォーマンスを向上させるために、6 つのキューブ面のうち 3 つだけを描画することです。

手前のモデルだけを描画するコードサンプル

public BoundingFrustum フラスタム { get; プライベートセット; }

//Initialize 
Matrix viewProjection = View * Projection; 
Frustum = new BoundingFrustum(viewProjection); 

//Update 
Matrix viewProjection = View * Projection; 
Frustum.Matrix = viewProjection; 

//Check instance and make the instanceTransformation for draw 
foreach (var object in ListInstance.Where(m => Frustum.Contains(m.BoundingBox) != ContaintmentType.Disjoint) 
{
    instanceTransforms[index].Add(smallListInstance[i].Transform); 

} 
// And now draw ... 
于 2013-03-12T21:23:55.440 に答える