Sepertinya jawaban yang tepat untuk ini adalah dengan melewatkan ContentPipeline dan menggunakan Texture2D.FromStream untuk memuat tekstur saat runtime. Metode ini berfungsi dengan baik di PC dan meskipun akan ada kinerja kecil hit ini adalah sesuatu yang bisa saya optimalkan begitu saya lebih dekat dengan tanggal rilis. Untuk saat ini, memiliki kemampuan memodifikasi konten untuk editor dan game secara dinamis adalah hal yang saya butuhkan. Setelah konten dibekukan, saya dapat mengoptimalkan ini dengan kembali ke ContentPipeline.
Karena Anda telah memilih rute ini, saya harus memperingatkan Anda bahwa itu sebenarnya tidak sesederhana hanya menggunakan Texture2D.FromStream
karena dua alasan:
Masalah # 1 - Kurangnya dukungan alpha pra-dikalikan
XNA4 sekarang menangani tekstur dengan warna dalam format alfa pra-ditanamkan secara default. Ketika Anda memuat tekstur melalui pipa konten, pemrosesan itu dilakukan untuk Anda secara otomatis. Sayangnya Texture2D.FromStream
tidak melakukan hal yang sama, sehingga tekstur apa pun yang memerlukan tingkat transparansi tertentu akan dimuat dan ditampilkan secara tidak benar. Di bawah ini adalah tangkapan layar untuk menggambarkan masalah:
Jadi untuk mendapatkan hasil yang benar, Anda perlu melakukan pemrosesan sendiri. Metode yang akan saya tunjukkan menggunakan GPU untuk melakukan pemrosesan sehingga cukup cepat. Itu didasarkan pada artikel bagus ini . Tentu saja Anda juga bisa menginstruksikan SpriteBatch
untuk merender dalam mode NonPremultiplyAlpha lama tapi saya tidak benar-benar merekomendasikan melakukan itu.
Masalah # 2 - Format yang tidak didukung
Pipa konten mendukung lebih banyak format daripada Texture2D.FromStream
. Secara khusus, Texture2D.FromStream
hanya mendukung png, jpg, dan gif. Di sisi lain, pipa konten mendukung bmp, dds, dib, hdr, jpg, pfm, png, ppm, dan tga. Jika Anda mencoba memuat format yang kami gunakan, Texture2D.FromStream
Anda akan mendapat InvalidOperationException
sedikit informasi tambahan.
Saya benar-benar membutuhkan dukungan bmp di mesin saya jadi untuk kasus khusus itu saya menemukan solusi yang tampaknya berfungsi dengan baik. Saya tidak tahu tentang format lainnya. Tangkapan dengan metode saya adalah bahwa Anda perlu menambahkan referensi ke System.Drawing
perakitan ke proyek Anda, karena menggunakan GDI Image.FromStream
yang mendukung lebih banyak format daripada Texture2D.FromStream
.
Jika Anda tidak peduli tentang dukungan bmp, Anda dapat dengan mudah menjatuhkan bagian dari solusi saya dan cukup melakukan pemrosesan alfa yang telah dikalikan.
Solusi - Versi Sederhana (Lebih Lambat)
Pertama-tama, inilah solusi paling sederhana jika Anda tidak peduli tentang dukungan bmps. Dalam contoh ini, tahap pemrosesan dilakukan sepenuhnya pada CPU. Ini sedikit lebih lambat daripada alternatif yang akan saya tunjukkan di bawah ini (saya melakukan benchmark kedua solusi) tetapi lebih mudah untuk dipahami:
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;
}
Jika Anda peduli tentang bmps maka hal yang perlu Anda lakukan adalah memuat gambar dengan GDI terlebih dahulu dan kemudian dikonversi menjadi PNG secara internal sebelum meneruskannya Texture2D.FromStream
. Berikut kode yang melakukan itu:
// 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);
}
}
Solusi - Versi Kompleks (Lebih Cepat)
Akhirnya, pendekatan yang saya gunakan pada proyek saya adalah menggunakan GPU untuk melakukan pemrosesan. Dalam metode ini Anda perlu membuat target render, mengatur beberapa negara campuran dengan benar, dan menggambar dua kali gambar dengan SpriteBatch. Pada akhirnya saya membahas seluruh RenderTarget2D dan mengkloning konten menjadi objek Texture2D yang terpisah karena RenderTarget2D mudah berubah dan tidak akan bertahan seperti mengubah ukuran backbuffer sehingga lebih aman untuk membuat salinan.
Yang lucu adalah bahwa bahkan dengan semua ini, pada tes saya pendekatan ini dilakukan sekitar 3 kali lebih cepat daripada pendekatan CPU. Jadi secara definitif lebih cepat daripada melewati setiap piksel dan menghitung warnanya sendiri. Kode ini agak panjang jadi saya menempatkannya di pastebin:
http://pastie.org/3651642
Cukup tambahkan kelas itu ke proyek Anda, dan gunakan sesederhana itu:
TextureLoader textureLoader = new TextureLoader(GraphicsDevice);
Texture2D texture = textureLoader.FromFile("Content/texture.png");
Catatan: Anda hanya perlu membuat satu TextureLoader
instance untuk seluruh game. Saya juga menggunakan perbaikan BMP tetapi Anda bisa mengeluarkannya jika Anda tidak perlu dan mendapatkan banyak kinerja, atau biarkan saja needsBmp
parameternya salah.
FromStream
dengan aliran memori yang mengandung bitmap 32bit (disimpan ke png), seperti contoh Anda yang lain, tetapi metode ini tidak membuat tekstur yang di-pre-multiplikasi. Secara eksplisit melakukan pra-evolusi setiap warna berhasil, terima kasih.Saya pikir sebagian besar tim akan melakukan perubahan xnb (well, semua perubahan benar-benar, termasuk xnb termasuk) ke server svn mereka (yang dapat diatur secara gratis) dan memungkinkan orang lain (artis, dll.) Untuk memperbarui salinan kerja mereka sendiri.
Bahkan, itu akan menjadi mekanisme yang baik bagi artis untuk mengontrol versi seni asli (pra-xnb). Dia akan melakukan perubahan itu, Anda akan memperbarui copy pekerjaan Anda itu, membangunnya (menjadikannya xnb dalam proses), mengkomit perubahan Anda, ia memperbarui copy pekerjaannya dari pekerjaan Anda dan dan semua orang memiliki semua perubahan. (Anda memiliki karya seni mentah terbaru, ia memiliki xnb (s).
Timbangan ini juga sangat baik.
sumber
Saya terus menyelidiki ini dan akan memposting ini untuk kepentingan seseorang yang memiliki pertanyaan yang sama.
Sepertinya jawaban yang tepat untuk ini adalah dengan melewatkan ContentPipeline dan menggunakan Texture2D.FromStream untuk memuat tekstur saat runtime. Metode ini berfungsi dengan baik di PC dan meskipun akan ada kinerja kecil hit ini adalah sesuatu yang bisa saya optimalkan begitu saya lebih dekat dengan tanggal rilis.
Untuk saat ini, memiliki kemampuan memodifikasi konten untuk editor dan game secara dinamis adalah hal yang saya butuhkan. Setelah konten dibekukan, saya dapat mengoptimalkan ini dengan kembali ke ContentPipeline.
sumber
Texture2D.FromStream
dengan sendirinya tidak cukup. Alasan untuk itu adalah karena versi 4 XNA bekerja dengan tekstur alfa yang telah di-preultiplied, dan sementara pipa konten menangani proses ini secara otomatis untuk Anda,Texture2D.FromStream
tidak jadi Anda mungkin akan mengalami masalah ketika menggambar sprite dengan transparansi. Saya dapat memposting solusi yang berfungsi jika Anda mau.Texture2D.FromStream
tidak mendukung memuat.BMP
file sementara pipa konten tidak. Ini adalah sesuatu yang mungkin akan membuang Anda jika Anda menggunakan.BMP
aset sebelumnya dan kemudian beralih keTexture2D.FromStream
. Saya juga punya solusi untuk batasan itu. Saya hanya akan pergi ke depan dan mempostingnya.Lihat proyek ini .
Ini akan memungkinkan artis Anda membuat XNB dari apa saja yang didukung oleh pipa konten XNA standar. Kerangka kerja XNA yang dapat didistribusikan masih diperlukan meskipun artis Anda tidak memerlukan Visual Studio.
sumber