2011-06-02 4 views
6

Ok, je 80000 « Box » Mesh avec des textures simples J'ai mis une distance de vue et dessiner seulement ceux que vous pouvez voir qui laisse 600 à 1000 pour la fonction DrawModel belowe Le problume est-ce que je reçois seulement 10 images par seconde et ma distance de vue est merdique Aussi, j'ai fait un test de mémoire à tout mon code et le "mesh.draw()" prend 30 Frame par seconde off. rien d'autre ne prend autant. Toute aide?C# XNA faible frame rate

 private void DrawModel(MeshHolder tmpMH) 
     {   
      Model tmpDrawModel = (Model)_Meshs[tmpMH.MeshFileName]; 
      Matrix[] transforms = new Matrix[tmpDrawModel.Bones.Count]; 
      tmpDrawModel.CopyAbsoluteBoneTransformsTo(transforms); 
      foreach (ModelMesh mesh in tmpDrawModel.Meshes) 
      { 
       foreach (BasicEffect effect in mesh.Effects) 
       { 

        effect.LightingEnabled = false; 

        effect.TextureEnabled = true; 
        effect.Texture = (Texture2D)_Textures[tmpMH.GetTexture(Count)]; 



        effect.View = _MainCam.View; 
        effect.Projection = _projection; 
        effect.World = 
         transforms[mesh.ParentBone.Index] * 
         Matrix.CreateFromYawPitchRoll(tmpMH.Rotation.Y, tmpMH.Rotation.X, tmpMH.Rotation.Z) * 
         Matrix.CreateScale(tmpMH.Scale) * 
         Matrix.CreateTranslation(tmpMH.Position); 
       } 

        mesh.Draw();    
      } 
     } 
+1

PC? Xbox 360? Téléphone Windows? –

+0

Ceci est très similaire à [cette question] (http://stackoverflow.com/questions/5268192/how-many-low-poly-models-can-xna-handle). –

Répondre

3
effect.World = 
    transforms[mesh.ParentBone.Index] * 
    Matrix.CreateFromYawPitchRoll(
     tmpMH.Rotation.Y, tmpMH.Rotation.X, tmpMH.Rotation.Z) * 
    Matrix.CreateScale(tmpMH.Scale) * 
    Matrix.CreateTranslation(tmpMH.Position); 

Je ne suis pas un profileur, mais je me sens de cette ligne est une douleur. La création de matrices et la multiplication sont assez chères! Je comprends que ce code est nécessaire, sauf si vous pouvez pré-calculer ces matrices, je vais essayer:

Matrix pitch, scale, translation, temp1, temp2; 

Matrix.CreateFromYawPitchRoll(
    tmpMH.Rotation.Y, tmpMH.Rotation.X, tmpMH.Rotation.Z, out pitch); 
Matrix.CreateScale(ref tmpMH.Scale, out scale); 
Matrix.CreateTranslation(ref tmpMH.Position, out translation); 
Matrix.Multiply(ref transforms[mesh.ParentBone.Index], ref pitch, out temp1); 
Matrix.Multiply(ref temp1, ref scale, out temp2); 
Matrix.Multiply(ref temp2, ref translation, out effect.World); 

Cela pourrait être plus rapide car il n'y a pas besoin de copier chaque matrice sur la pile pour le passage de paramètres (plus moins de 20 fois moins de choses à copier!)

+1

Je * doute * sérieusement que les calculs matriciels non-micro-optimisés dominent ici l'utilisation du processeur. De plus 'effect.World' ne peut pas être un paramètre' out'. –

+0

@Andrew Russel: À mon avis, cela aidera. La copie de certaines choses est assez coûteuse non pas en termes d'utilisation du processeur, mais simplement parce que le processeur doit attendre la mémoire (http://en.wikipedia.org/wiki/Wait_state) – BlackBear

+0

Vous n'allez pas frapper mémoire principale avec l'une ou l'autre version du code. La petite quantité de données de pile ici s'insérera facilement dans le cache du processeur. Et mettre le CPU dans un état d'attente (comme par défaut de cache) compte toujours comme "utilisation" vers la limite de votre CPU. Votre code va "aider", car il nécessite moins d'instructions - mais seulement par un * minuscule * montant - et certainement pas assez pour obtenir l'OP en dessous de la limite du CPU. –

7

Qu'est-ce qui tue votre performance - comme vous le dites - est ModelMesh.Draw. Lorsque vous dessinez des modèles, cela fonctionne comme ceci:

for each frame 
    for each Model 
    for each ModelMesh // you call Draw(), which does: 
     for each ModelMeshPart 
     for each Effect 
      for each EffectPass 
      Draw some triangles // sends a batch of instructions to the GPU 

La question est: combien de fois chaque image envoyez-vous un lot au GPU? Parce que vous ne pouvez envoyer que quelques milliers de lots * par image avant de saturer le CPU - en frappant la "limite de lot". (Chaque lot utilise le temps CPU dans le pilote graphique - il utilise également une bande passante et le temps GPU, mais le temps CPU domine.)

Vous pouvez lire des informations supplémentaires this answer et this answer et this slide deck. La solution consiste à modifier votre scène (par exemple: combiner certaines parties de maillage, effectuer une sélection, ajouter un support d'instanciation) pour réduire le nombre de lots que vous envoyez au GPU.


Aussi, essayez d'éviter des choses comme ça dans votre Draw et Update boucle:

Matrix[] transforms = new Matrix[tmpDrawModel.Bones.Count]; 

Vous devriez vraiment faire de votre mieux pour éviter les allocations de mémoire qui se produisent chaque image - comme ils finiront par provoquer une garbage collection cher et potentiellement un hiccup de frame-rate (en particulier sur Xbox). Essayez de stocker votre tampon quelque part et réutilisez-le.

+0

Merci, cela aide vraiment. – codegreen

+1

Le lien BatchBatchBatch.pdf ne semble pas fonctionner maintenant. En voici un qui fonctionne: http://origin-developer.nvidia.com/docs/IO/8230/BatchBatchBatch.pdf?q=docs/IO/8230/BatchBatchBatch.pdf – Venesectrix

+0

Celui-là aussi est cassé, maintenant. Je l'ai mis à jour à un nouveau qui fonctionne. –