Utilizzo di XNA ContentPipeline per esportare un file in un computer senza XNA GS completo


9

Il mio gioco utilizza la pipeline di contenuti per caricare spriteSheet in fase di esecuzione. L'artista del gioco mi invia lo spritesheet modificato e faccio una build nella mia macchina e gli invio un progetto aggiornato. Quindi sto cercando un modo per generare i file xnb nella sua macchina (questo è l'output della pipeline di contenuti) senza che debba installare l'intero XNA Game Studio.

1) Non voglio che il mio artista installi VS + Xna (so che esiste una versione gratuita di VS ma questo non si ridimensionerà una volta aggiunte altre persone al team). 2) Non sono interessato a eseguire questo editor / strumento su Xbox, quindi una soluzione solo per Windows funziona. 3) Sono a conoscenza delle opzioni di MSBuild ma richiedono XNA completo

Ho studiato il blog di Shawn e ho trovato l'opzione di utilizzare Msbuild Sample o una nuova opzione in XNA 4.0 che sembrava promettente qui ma sembra avere le stesse restrizioni: è necessario installare XNA GS completo perché ContentPipeline non fa parte del redist di XNA.

Qualcuno ha trovato una soluzione alternativa per questo?

Risposte:


11

Sembra che la risposta giusta a questa sia saltare la ContentPipeline e usare Texture2D.FromStream per caricare le trame in fase di esecuzione. Questo metodo funziona bene su un PC e anche se ci saranno piccole prestazioni, questo è qualcosa che posso ottimizzare una volta più vicino alla data di rilascio. Per ora, avere la possibilità di modificare dinamicamente il contenuto sia per l'editor che per il gioco è esattamente ciò di cui ho bisogno. Una volta congelato il contenuto, posso ottimizzarlo tornando alla ContentPipeline.

Dato che hai scelto questa strada, ti avverto che in realtà non è così semplice come usare solo Texture2D.FromStreamper due motivi:

Problema n. 1 - Mancanza di supporto alfa pre-moltiplicato

XNA4 ora gestisce trame con colori in formato alfa premoltiplicato per impostazione predefinita. Quando si carica una trama attraverso la pipeline di contenuti, tale elaborazione viene eseguita automaticamente. Sfortunatamente Texture2D.FromStreamnon fa la stessa cosa, quindi tutte le trame che richiedono un certo grado di trasparenza verranno caricate e renderizzate in modo errato. Di seguito è riportato uno screenshot per illustrare il problema:

inserisci qui la descrizione dell'immagine

Quindi, al fine di ottenere i risultati corretti, è necessario eseguire l'elaborazione da soli. Il metodo che mostrerò usa la GPU per eseguire l'elaborazione, quindi è piuttosto veloce. Era basato su questo fantastico articolo . Ovviamente potresti anche istruire il SpriteBatchrendering nella vecchia modalità NonPremultiplyAlpha, ma non ti consiglio di farlo.

Problema n. 2 - Formati non supportati

La pipeline di contenuti supporta più formati di Texture2D.FromStream. In particolare, Texture2D.FromStreamsupporta solo png, jpg e gif. D'altra parte, la pipeline di contenuti supporta bmp, dds, dib, hdr, jpg, pfm, png, ppm e tga. Se provi a caricare un formato usuported tramite Texture2D.FromStreamotterrai un InvalidOperationExceptionpo 'di informazioni aggiuntive.

Avevo davvero bisogno del supporto bmp sul mio motore, quindi per quel caso particolare ho trovato una soluzione che sembra funzionare bene. Non conosco nessuno degli altri formati però. Il problema con il mio metodo è che è necessario aggiungere un riferimento System.Drawingall'assembly al progetto, perché utilizza GDI Image.FromStreamche supporta più formati di Texture2D.FromStream.

Se non ti interessa supportare bmp, puoi facilmente abbandonare quella parte della mia soluzione e fare semplicemente l'elaborazione alfa pre-moltiplicata.

Soluzione - Versione semplice (più lenta)

Prima di tutto, ecco la soluzione più semplice se non ti interessa supportare bmps. In questo esempio la fase di elaborazione viene eseguita interamente sulla CPU. È un po 'più lento dell'alternativa che mostrerò di seguito (ho fatto un benchmark di entrambe le soluzioni) ma più facile da capire:

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;
}

Se ti interessa bmps, la cosa che devi fare è caricare prima l'immagine con GDI e poi convertirla in PNG internamente prima di passarla a Texture2D.FromStream. Ecco il codice che lo fa:

// 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);
    }
}

Soluzione - Versione complessa (più veloce)

Infine, l'approccio che utilizzo nei miei progetti è quello di utilizzare la GPU per eseguire l'elaborazione. In questo metodo è necessario creare una destinazione di rendering, impostare correttamente alcuni stati di fusione e disegnare due volte l'immagine con uno SpriteBatch. Alla fine vado sull'intero RenderTarget2D e clono il contenuto in un oggetto Texture2D separato perché RenderTarget2D è volatile e non sopravvive a cose come la modifica delle dimensioni del backbuffer, quindi è più sicuro fare una copia.

La cosa divertente è che anche con tutto ciò, nei miei test questo approccio ha funzionato circa 3 volte più veloce dell'approccio CPU. Quindi è decisamente più veloce che andare su ogni pixel e calcolare tu stesso il colore. Il codice è un po 'lungo, quindi l'ho inserito in un pastebin:

http://pastie.org/3651642

Aggiungi quella classe al tuo progetto e usala come:

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

Nota: devi solo creare TextureLoaderun'istanza per l'intero gioco. Inoltre sto usando la correzione BMP ma puoi eliminarla se non ti serve e ottenere un sacco di prestazioni, o semplicemente lasciare il needsBmpparametro come falso.


wow, è fantastico! Mi aiuterà molto :) Grazie mille David, lo apprezzo.
Krolth,

+1 In realtà, stavo usando FromStreamun flusso di memoria contenente una bitmap a 32 bit (salvata in png), proprio come il tuo altro esempio, ma questo metodo non ha creato una trama premoltiplicata. La premiscela esplicita di ogni colore ha funzionato, grazie.
Groo

3

Penso che la maggior parte dei team apporterebbe le modifiche xnb (beh, tutte le modifiche in realtà, xnb incluso) al loro server svn (che può essere impostato gratuitamente) e consentire ad altri (l'artista, ecc.) Di aggiornare le proprie copie di lavoro.

In effetti, sarebbe un buon meccanismo per l'artista per controllare la versione dell'arte originale (pre-nb). Commetterebbe delle modifiche a questo, aggiorneresti la tua copia di lavoro, la costruiresti (rendendola una xnb nel processo), commetterebbe le tue modifiche, aggiorna la sua copia di lavoro del tuo lavoro e tutti hanno tutte le modifiche. (Hai l'ultima grafica grezza, ha gli xnb.

Anche questo si adatta molto bene.


Quindi stai dicendo che non pensi che possa essere fatto? Il tuo suggerimento è l'aggiunta del controllo della versione a XNB e agli sprite, lo stiamo già facendo. Ma non mi piace perché divento il collo di bottiglia per loro. Ho già scritto uno strumento per loro per modificare le animazioni e possono provarle nel gioco. Ma se apportano modifiche allo spritesheet devono aspettare fino a quando lo costruisco prima che possano vederlo. Come puoi immaginare se commettono un errore, devono farlo di nuovo.
Krolth,

@krolth È così importante che i tuoi artisti ottengano VS Express e XNA come parte della loro installazione per lavorare su un progetto? Penso che a questo punto il compromesso di dover scrivere una guida e aiutare le persone attraverso di essa supererà di gran lunga la produttività che stai perdendo ora poiché gli artisti non possono vedere il loro lavoro nel motore. Per semplificare il processo, dai loro un file .BAT su cui possono fare doppio clic per ricompilare tutto senza dover aprire l'IDE. E se stanno eseguendo solo OS X, beh, merda dura. Benvenuto in game dev. Possono impegnare i loro sprite e attendere i prossimi XNB impegnati.
michael.bartnett,

non è un grosso problema, solo un dolore. Ma suppongo che dovrà fare. Grazie a tutti per le vostre risposte / commenti!
Krolth,

1

Ho continuato a indagare su questo e pubblicherò questo a beneficio di qualcuno che ha la stessa domanda.

Sembra che la risposta giusta a questa sia saltare la ContentPipeline e usare Texture2D.FromStream per caricare le trame in fase di esecuzione. Questo metodo funziona bene in un PC e, anche se ci sarà un piccolo spettacolo ha colpito questo è qualcosa che posso ottimizzare una volta che sono più vicino alla data di uscita.

Per ora, avere la possibilità di modificare dinamicamente il contenuto sia per l'editor che per il gioco è esattamente ciò di cui ho bisogno. Una volta congelato il contenuto, posso ottimizzarlo tornando alla ContentPipeline.


Hai provato questo correttamente? Dalla mia esperienza Texture2D.FromStreamda sola non basta. La ragione di ciò è che dalla versione 4 XNA funziona con trame alfa premoltiplicate, e mentre la pipeline di contenuti si occupa automaticamente di questa elaborazione per te, Texture2D.FromStreamnon è così che probabilmente incontrerai problemi quando si disegnano gli sprite con trasparenza. Posso pubblicare una soluzione funzionante, se lo desideri.
David Gouveia,

Inoltre, Texture2D.FromStreamnon supporta il caricamento di .BMPfile mentre lo fa la pipeline di contenuti. Questo è qualcosa che probabilmente ti butterebbe via se avessi usato .BMPrisorse in precedenza e poi passassi a Texture2D.FromStream. Ho anche una soluzione per tale limitazione. Vado avanti e pubblicherò.
David Gouveia,

0

Dai un'occhiata a questo progetto .

Permetterà al tuo artista di creare XNB praticamente da qualsiasi cosa supportata dalla pipeline di contenuti XNA predefinita. Il framework XNA ridistribuibile è ancora necessario sebbene il tuo artista non abbia bisogno di Visual Studio.


Grazie per il puntatore. Guardando il codice sembra una modifica all'esempio Microsoft a cui ho fatto riferimento. Dipende dall'installazione di XNA Game Studio completo (vedi ContentBuilder.cs). Perché pensi che non lo faccia?
Krolth

Non penso che non lo sia. Se si desidera utilizzare la pipeline di contenuti, è necessario disporre dello studio di gioco completo. Tuttavia, il progetto impedisce ai tuoi artisti di utilizzare Visual Studio. Le uniche altre alternative per riscrivere la pipeline di contenuti.
ClassicThunder
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.