IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XNA/Monogame Discussion :

Comment dessiner des millions de cubes, instanciation dans XNA?


Sujet :

XNA/Monogame

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2010
    Messages : 96
    Points : 72
    Points
    72
    Par défaut Comment dessiner des millions de cubes, instanciation dans XNA?
    Je travaille pour un projet dans le style de jeu "Minecraft".

    J'ai commencé à utiliser la "Instanciation du modèle" afin de générer un grand nombre de cubes qui possèdent un modèle identique.
    Jusqu'ici tout va bien.
    Mon problème est que si je augmente la taille de ma matrice de dessin [300-1-300] (** 90.000 mètres cubes **) à [500-1-500] (** 250.000 mètres cubes **) mon programme ralentit énormément. Il va de 60fps à 20 ...

    Je ne comprends pas vraiment pourquoi. Mais j'utilise la technique correctement "Hardware Instancing». J'ai aussi remarqué sur les forums que cette technique sur XNA permet de dessiner jusqu'à 7 millions de cubes!
    Avez-vous une idée d'où mon problème?

    Merci beaucoup


    Voici ma fonction qui dessine le modèle instancié :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
       // 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
    Voici ma fonction DrawModelHardwareInstancing qui dessine avec l'instanciation matérielle, comme utilisé dans l'exemple de Microsoft.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
    // 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

  2. #2
    Membre expert

    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2006
    Messages
    1 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 1 031
    Points : 3 092
    Points
    3 092
    Par défaut
    Tout simplement que l'instancing n'est pas la bonne méthode

    Je te laisse la découvrir ici : http://techcraft.codeplex.com/
    Suivez le développement de Chibis Bomba
    twitter : https://twitter.com/MoD_DiB
    DevBlog : http://moddib.blogspot.fr/

  3. #3
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2010
    Messages : 96
    Points : 72
    Points
    72
    Par défaut
    Oui merci beaucoup . Je connaissais déja ce projet ! Cependant je le trouvais un peux compliqué dans leur façon de coder ^^ Il y manque pas mal de commentaires et manque d'exemple et documentation sur codePlex .. Ou c'est peut être moi qui suis trop noob.

    Si le projet techcraft n'utilise pas l'instancing , pouvez vous me dire qu'el methode utilise t-il ?

    J'ai tout de meme en attendant réussi à ne dessiner que ce que la camera voit devant elle. Je pensais encore à dessiner que 3 faces maximum d'un cube sur les 6 . Comme il est impossible de voir les 6 en même temps.
    Sinon aussi transformer plusieurs petits cubes en 1 seul grand cube. afin de diminuer la charge.
    Cela est -til utile ou non d'après vous ?
    Merci énormément.

  4. #4
    Membre expert

    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2006
    Messages
    1 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 1 031
    Points : 3 092
    Points
    3 092
    Par défaut
    Concrètement le but est de réduire le nombre de drawcalls.
    Pour cela le but est de rassembler un maximum de cubes dans la même géometrie : ce qui signifie qu'à chaque modification du terrain le maillage est modifié.
    De cette manière il est aussi possible de supprimer les faces qui ne seront jamais visibles puisque'elles sont à l'intérieur du terrain.
    Suivez le développement de Chibis Bomba
    twitter : https://twitter.com/MoD_DiB
    DevBlog : http://moddib.blogspot.fr/

  5. #5
    Membre régulier
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Décembre 2010
    Messages
    96
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Décembre 2010
    Messages : 96
    Points : 72
    Points
    72
    Par défaut
    Euh oui c'est effectivement ce que je pensais faire... Mais comment séléctionner les faces visible ou cacher celle non visible ? Et sinon .. pourquoi l'instancing n'est pas une bonne idée ?

  6. #6
    Membre expert

    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Février 2006
    Messages
    1 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2006
    Messages : 1 031
    Points : 3 092
    Points
    3 092
    Par défaut
    Citation Envoyé par middle6 Voir le message
    Euh oui c'est effectivement ce que je pensais faire... Mais comment séléctionner les faces visible ou cacher celle non visible ? Et sinon .. pourquoi l'instancing n'est pas une bonne idée ?
    En vérifiant si il y a un cube a coté : un cube à coté = 1 face en moins ; ce qui signifie que si il y a 4 cubes tout autour le cube n'est plus affiché.

    Dans la mesure où il y a quasiment 95% des cubes qui ne sont pas visibles car recouvert l'instancing ne sera pas efficace; en affichant uniquement les cubes extérieurs ca serait deja mieux mais pas encore optimal par rapport à la méthode précédente.
    Suivez le développement de Chibis Bomba
    twitter : https://twitter.com/MoD_DiB
    DevBlog : http://moddib.blogspot.fr/

Discussions similaires

  1. Réponses: 4
    Dernier message: 29/08/2006, 14h52
  2. [POO] Comment acceder a un objet javascript instancie dans une page mere
    Par herbert dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 20/07/2006, 19h34
  3. Réponses: 1
    Dernier message: 11/05/2006, 16h23
  4. comment dessiner des courbes en c++builder?
    Par bob75018 dans le forum C++Builder
    Réponses: 8
    Dernier message: 17/01/2006, 20h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo