Utilisation de XNA ContentPipeline pour exporter un fichier dans une machine sans XNA GS complet


9

Mon jeu utilise le Pipeline de contenu pour charger le spriteSheet lors de l'exécution. L'artiste du jeu m'envoie la feuille de calcul modifiée et je fais un build dans ma machine et lui envoie un projet mis à jour. Je cherche donc un moyen de générer les fichiers xnb sur sa machine (c'est la sortie du pipeline de contenu) sans qu'il ait à installer le studio XNA Game complet.

1) Je ne veux pas que mon artiste installe VS + Xna (je sais qu'il existe une version gratuite de VS mais cela ne sera pas mis à l'échelle une fois que nous ajouterons plus de personnes à l'équipe). 2) Je ne suis pas intéressé par l'exécution de cet éditeur / outil sur Xbox, donc une solution Windows uniquement fonctionne. 3) Je connais les options MSBuild mais elles nécessitent XNA complet

J'ai fait des recherches sur le blog de Shawn et j'ai trouvé l'option d'utiliser Msbuild Sample ou une nouvelle option dans XNA 4.0 qui semblait prometteuse ici mais qui semble avoir la même restriction: besoin d'installer XNA GS complet parce que ContentPipeline ne fait pas partie de la redistribution XNA.

Est-ce que quelqu'un a trouvé une solution à cela?

Réponses:


11

Il semble que la bonne réponse à cela soit d'ignorer ContentPipeline et d'utiliser Texture2D.FromStream pour charger les textures lors de l'exécution. Cette méthode fonctionne bien sur un PC et même s'il y aura une petite baisse de performances, c'est quelque chose que je peux optimiser une fois que je suis plus proche de la date de sortie. Pour l'instant, avoir la possibilité de modifier dynamiquement le contenu de l'éditeur et du jeu est exactement ce dont j'ai besoin. Une fois que le contenu est gelé, je peux l'optimiser en revenant à ContentPipeline.

Puisque vous avez choisi cette voie, je dois vous avertir que ce n'est pas aussi simple que de simplement l'utiliser Texture2D.FromStreampour deux raisons:

Problème n ° 1 - Manque de support alpha pré-multiplié

XNA4 gère désormais les textures avec des couleurs au format alpha prémultiplié par défaut. Lorsque vous chargez une texture via le pipeline de contenu, ce traitement est effectué automatiquement pour vous. Malheureusement, Texture2D.FromStreamne fait pas la même chose, donc toutes les textures qui nécessitent un certain degré de transparence seront chargées et rendues incorrectement. Voici une capture d'écran pour illustrer le problème:

entrez la description de l'image ici

Donc, pour obtenir les bons résultats, vous devez effectuer le traitement vous-même. La méthode que je vais montrer utilise le GPU pour faire le traitement, donc c'est assez rapide. Il était basé sur ce grand article . Bien sûr, vous pouvez également demander SpriteBatchde rendre dans l'ancien mode NonPremultiplyAlpha mais je ne recommande pas vraiment de le faire.

Problème n ° 2 - Formats non pris en charge

Le pipeline de contenu prend en charge plus de formats que Texture2D.FromStream. En particulier, Texture2D.FromStreamne prend en charge que les formats png, jpg et gif. D'un autre côté, le pipeline de contenu prend en charge bmp, dds, dib, hdr, jpg, pfm, png, ppm et tga. Si vous essayez de charger un format usuporté, Texture2D.FromStreamvous obtiendrez un InvalidOperationExceptionavec peu d'informations supplémentaires.

J'avais vraiment besoin du support bmp sur mon moteur, donc pour ce cas particulier, j'ai trouvé une solution de contournement qui semble fonctionner correctement. Je ne connais cependant aucun des autres formats. Le problème avec ma méthode est que vous devez ajouter une référence à l' System.Drawingassembly à votre projet, car il utilise des GDI Image.FromStreamqui prennent en charge plus de formats que Texture2D.FromStream.

Si vous ne vous souciez pas de la prise en charge de bmp, vous pouvez facilement supprimer cette partie de ma solution et simplement effectuer le traitement alpha pré-multiplié.

Solution - Version simple (plus lente)

Tout d'abord, voici la solution la plus simple si vous ne vous souciez pas de la prise en charge de bmps. Dans cet exemple, l'étape de traitement se fait entièrement sur le CPU. C'est un peu plus lent que l'alternative que je vais montrer ci-dessous (j'ai testé les deux solutions) mais plus facile à comprendre:

public static Texture2D FromStream(GraphicsDevice graphicsDevice, Stream stream)
{
    Texture2D texture = Texture2D.FromStream(graphicsDevice, stream);
    Color[] data = new Color[texture.Width * texture.Height];
    texture.GetData(data);
    for (int i = 0; i != data.Length; ++i)
        data[i] = Color.FromNonPremultiplied(data[i].ToVector4());
    texture.SetData(data);
    return texture;
}

Si vous vous souciez des bmps, la chose que vous devez faire est de charger d'abord l'image avec GDI, puis de la convertir en PNG en interne avant de la passer à Texture2D.FromStream. Voici le code qui fait cela:

// Load image using GDI because Texture2D.FromStream doesn't support BMP
using (Image image = Image.FromStream(stream))
{
    // Now create a MemoryStream which will be passed to Texture2D after converting to PNG internally
    using (MemoryStream ms = new MemoryStream())
    {
        image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
        ms.Seek(0, SeekOrigin.Begin);
        texture = Texture2D.FromStream(_graphicsDevice, ms);
    }
}

Solution - Version complexe (plus rapide)

Enfin, l'approche que j'utilise dans mes projets est d'utiliser le GPU pour faire le traitement à la place. Dans cette méthode, vous devez créer une cible de rendu, configurer correctement certains états de fusion et dessiner l'image deux fois avec un SpriteBatch. À la fin, je passe en revue l'ensemble du RenderTarget2D et clone le contenu dans un objet Texture2D distinct car le RenderTarget2D est volatile et ne survivra pas à des choses comme la modification de la taille du backbuffer, il est donc plus sûr de faire une copie.

Le plus drôle, c'est que même avec tout cela, lors de mes tests, cette approche a fonctionné environ 3 fois plus vite que l'approche CPU. C'est donc définitivement plus rapide que de parcourir chaque pixel et de calculer la couleur vous-même. Le code est un peu long donc je l'ai placé dans une boîte à pâte:

http://pastie.org/3651642

Ajoutez simplement cette classe à votre projet et utilisez-la aussi simplement que:

TextureLoader textureLoader = new TextureLoader(GraphicsDevice);
Texture2D texture = textureLoader.FromFile("Content/texture.png");

Remarque: Vous n'avez besoin de créer qu'une seule TextureLoaderinstance pour l'ensemble du jeu. J'utilise également le correctif BMP, mais vous pouvez le supprimer si vous n'en avez pas besoin et gagner un tas de performances, ou tout simplement laisser le needsBmpparamètre faux.


wow, c'est super! Cela m'aidera beaucoup :) Merci beaucoup David, je l'apprécie.
krolth

+1 En fait, j'utilisais FromStreamavec un flux de mémoire contenant un bitmap 32 bits (enregistré en png), tout comme votre autre exemple, mais cette méthode n'a pas créé de texture prémultipliée. Prémultiplier explicitement chaque couleur a fait l'affaire, merci.
Groo

3

Je pense que la plupart des équipes commettraient les changements xnb (enfin, tous les changements vraiment, xnb inclus) sur leur serveur svn (qui peut être mis en place gratuitement) et permettraient à d'autres (l'artiste, etc.) de mettre à jour leurs propres copies de travail.

En fait, ce serait un bon mécanisme pour l'artiste pour contrôler la version de l'art original (pré-xnb). Il y apporterait des modifications, vous mettrez à jour votre copie de travail, la construirez (en faisant un xnb dans le processus), validera vos modifications, il mettra à jour sa copie de travail de votre travail et tout le monde a toutes les modifications. (Vous avez les dernières illustrations brutes, il a le ou les xnb).

Cela évolue très bien aussi.


Vous dites donc que vous ne pensez pas que cela puisse être fait? Votre suggestion est d'ajouter le contrôle de version au XNB et aux sprites, nous le faisons déjà. Mais je n'aime pas ça parce que je deviens le goulot d'étranglement pour eux. J'ai déjà écrit un outil pour éditer les animations et ils peuvent les essayer dans le jeu. Mais s'ils modifient la feuille de sprites, ils doivent attendre que je la construise avant de pouvoir la voir. Comme vous pouvez l'imaginer, s'ils font une erreur, ils doivent recommencer.
krolth

@krolth Est-ce si important que vos artistes obtiennent VS Express et XNA dans le cadre de leur configuration pour travailler sur un projet? Je pense qu'à ce stade, le compromis d'avoir à rédiger un guide et à aider les gens à le parcourir dépassera de loin la productivité que vous perdez maintenant, car les artistes ne peuvent pas voir leur travail dans le moteur. Pour rationaliser le processus, donnez-leur un fichier .BAT sur lequel ils peuvent double-cliquer pour tout recompiler sans avoir à ouvrir l'IDE. Et s'ils n'exécutent que OS X, eh bien, merde. Bienvenue dans Game Dev. Ils peuvent valider leurs sprites et attendre les prochains XNB validés.
michael.bartnett

ce n'est pas si grave, juste une douleur. Mais je suppose que cela devra faire. Merci à tous pour vos réponses / commentaires!
krolth

1

J'ai continué à enquêter sur cela et je le publierai au profit de quelqu'un qui a la même question.

Il semble que la bonne réponse à cette question consiste à ignorer ContentPipeline et à utiliser Texture2D.FromStream pour charger les textures lors de l'exécution. Cette méthode fonctionne bien sur un PC et même s'il y aura une petite baisse de performances, c'est quelque chose que je peux optimiser une fois que je suis plus proche de la date de sortie.

Pour l'instant, avoir la possibilité de modifier dynamiquement le contenu de l'éditeur et du jeu est exactement ce dont j'ai besoin. Une fois que le contenu est gelé, je peux l'optimiser en revenant à ContentPipeline.


L'avez-vous testé correctement? De mon expérience Texture2D.FromStreamen soi ne suffit pas. La raison en est que, depuis la version 4, XNA fonctionne avec des textures alpha prémultipliées, et bien que le pipeline de contenu se charge automatiquement de ce traitement pour vous, ce Texture2D.FromStreamn'est pas le cas, vous rencontrerez probablement des problèmes lors du dessin de sprites avec transparence. Je peux publier une solution de travail si vous le souhaitez.
David Gouveia

En outre, Texture2D.FromStreamne prend pas en charge le chargement de .BMPfichiers , contrairement au pipeline de contenu. C'est quelque chose qui vous découragerait probablement si vous utilisiez des .BMPactifs auparavant, puis que vous passiez à Texture2D.FromStream. J'ai également une solution de contournement pour cette limitation. Je vais juste aller de l'avant et l'afficher.
David Gouveia

0

Découvrez ce projet .

Cela permettra à votre artiste de créer XNB à partir de tout ce que le pipeline de contenu XNA par défaut prend en charge. Le framework XNA redistribuable est toujours nécessaire bien que votre artiste n'ait pas besoin de Visual Studio.


Merci pour le pointeur. En regardant le code, cela ressemble à une modification de l'exemple Microsoft auquel j'ai fait référence. Cela dépend de l'installation complète de XNA Game Studio (voir ContentBuilder.cs). Pourquoi pensez-vous que ce n'est pas le cas?
krolth

Je ne pense pas que ce ne soit pas le cas. Si vous souhaitez utiliser le pipeline de contenu, vous devez disposer du studio de jeu complet. Cependant, le projet empêche vos artistes d'avoir à utiliser Visual Studio. Les seules autres alternatives pour réécrire le pipeline de contenu.
ClassicThunder
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.