Використання XNA ContentPipeline для експорту файлу в машину без повної XNA GS


9

Моя гра використовує контент-конвеєр для завантаження spriteSheet під час виконання. Художник для гри надсилає мені модифікований спрайт-лист, і я будую машину на своїй машині і надсилаю йому оновлений проект. Тому я шукаю спосіб генерувати файли xnb на своїй машині (це вихід конвеєра контенту), не маючи необхідності встановлювати повну студію XNA Game Studio.

1) Я не хочу, щоб мій художник встановлював VS + Xna (я знаю, що є безкоштовна версія VS, але це не зміниться, коли ми додамо більше людей до команди). 2) Мені не цікаво запускати цей редактор / інструмент у Xbox, тому рішення, що працює лише для Windows. 3) Мені відомі варіанти MSBuild, але для них потрібна повна XNA

Я досліджував блог Шона і знайшов можливість використовувати Msbuild Sample або новий варіант у XNA 4.0, який виглядав тут багатообіцяюче, але, здається, він має таке ж обмеження: Потрібно встановити повний XNA GS, оскільки ContentPipeline не є частиною переліку XNA.

Так хтось знайшов вирішення цього питання?

Відповіді:


11

Вірна відповідь на це полягає в тому, щоб пропустити ContentPipeline і використовувати Texture2D.FromStream для завантаження текстур під час виконання. Цей метод відмінно працює на ПК, і, хоча буде невеликий показник продуктивності, це те, що я можу оптимізувати, коли наближуся до дати випуску. Наразі мені потрібна можливість динамічно змінювати контент як для редактора, так і для гри саме те, що мені потрібно. Як тільки вміст буде заморожено, я можу оптимізувати це, повернувшись до ContentPipeline.

Оскільки ви вибрали цей маршрут, я повинен попередити вас, що насправді це не так просто, як просто використовувати Texture2D.FromStreamз двох причин:

Проблема №1 - Відсутність попередньо розмноженої підтримки альфа

XNA4 тепер обробляє текстури кольорами у попередньо промноженому альфа-форматі за замовчуванням. Коли ви завантажуєте текстуру через контент конвеєра, ця обробка проводиться автоматично. На жаль, Texture2D.FromStreamце не робить те ж саме, тому будь-які текстури, які потребують певної ступеня прозорості, будуть завантажені та надані неправильно. Нижче наведено скріншот для ілюстрації проблеми:

введіть тут опис зображення

Отже, щоб отримати правильні результати, обробку потрібно зробити самостійно. Метод, який я покажу, використовує GPU для обробки, тому це досить швидко. Він був заснований на цій чудовій статті . Звичайно, ви можете також доручити SpriteBatchвізуалізувати у старому режимі NonPremultiplyAlpha, але я не рекомендую цього робити.

Проблема №2 - Непідтримувані формати

Контент конвеєра підтримує більше форматів, ніж Texture2D.FromStream. Зокрема, Texture2D.FromStreamпідтримує лише png, jpg та gif. З іншого боку, контент-конвеєр підтримує bmp, dds, dib, hdr, jpg, pfm, png, ppm та tga. Якщо ви спробуєте завантажити usutported формат, Texture2D.FromStreamви отримаєте InvalidOperationExceptionневелику додаткову інформацію.

Мені дуже потрібна підтримка bmp на моєму двигуні, тому для цього конкретного випадку я знайшов вирішення, яке, здається, працює нормально. Я не знаю про жоден з інших форматів. Мій метод полягає в тому, що вам потрібно додати посилання на System.Drawingзбірку до свого проекту, оскільки він використовує GDI, Image.FromStreamякі підтримують більше форматів, ніж Texture2D.FromStream.

Якщо ви не переймаєтесь підтримкою bmp, ви можете легко скинути цю частину мого рішення і просто виконати попередньо розмножену альфа-обробку.

Рішення - Проста версія (повільніше)

Перш за все, ось найпростіше рішення, якщо вам не байдуже підтримка бамперів. У цьому прикладі етап обробки повністю виконується на процесорі. Це трохи повільніше, ніж альтернатива, яку я покажу нижче (я зробив орієнтир обох рішень), але простіше зрозуміти:

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

Якщо ви дбаєте про штампи, то вам потрібно спочатку завантажити зображення в GDI, а потім перетворити всередині PNG, перш ніж передавати його Texture2D.FromStream. Ось код, який робить це:

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

Рішення - Складна версія (швидше)

Нарешті, підхід, який я використовую у своїх проектах, полягає у використанні GPU для обробки. У цьому методі вам потрібно створити ціль візуалізації, правильно встановити деякі стану суміші та двічі намалювати зображення за допомогою SpriteBatch. Наприкінці я переглядаю весь RenderTarget2D і клоную вміст в окремий об’єкт Texture2D, тому що RenderTarget2D є мінливим і не переживе таких речей, як зміна розміру резервного буфера, тому безпечніше зробити копію.

Найсмішніше, що навіть при всьому цьому, на моїх тестах цей підхід працював приблизно в 3 рази швидше, ніж підхід CPU. Тож, безумовно, швидше, ніж перебирати кожен піксель і самостійно обчислювати колір. Код трохи довгий, тому я помістив його в пастину:

http://pastie.org/3651642

Просто додайте цей клас до свого проекту та використовуючи його так просто, як:

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

Примітка. Вам потрібно створити лише один TextureLoaderекземпляр для всієї гри. Також я використовую виправлення BMP, але ви можете вийняти його, якщо вам це не потрібно, і ви отримаєте купу продуктивності, або просто залиште needsBmpпараметр помилковим.


вау, це чудово! Це мені дуже допоможе :) Дякую, Девід, я ціную це.
krolth

+1 Насправді я використовував FromStreamпотік пам'яті, що містить 32-бітову растрову карту (збережено в png), як і ваш інший приклад, але цей метод не створив попередньо множину текстури. Спасибі, явно попередньо помноживши кожен колір, вдалося.
Гроо

3

Я думаю, що більшість команд здійснить зміни xnb (ну, всі зміни дійсно, xnb includeud) на своєму сервері svn (який можна налаштувати безкоштовно) і дозволить іншим (виконавцю тощо) оновлювати власні робочі копії.

Насправді, це був би хороший механізм для виконавця контролювати версію оригінального (prexnb) мистецтва. Він вчинить зміни до цього, ви оновлюєте свою робочу копію, створюєте її (роблячи це xnb в процесі), вносите свої зміни, він оновлює свою робочу копію вашої роботи і всі мають усі зміни. (У вас є остання сира художня робота, у нього є xnb (s).

Це теж дуже добре.


Отже, ви говорите, що не думаєте, що це можна зробити? Ваша пропозиція додає керування версіями до XNB та спрайтів, ми це вже робимо. Але мені це не подобається, бо я став вузьким місцем для них. Я вже написав для них інструмент для редагування анімації, і вони можуть спробувати їх у грі. Але якщо вони внесуть зміни в таблицю спрацьовування, їм потрібно зачекати, поки я будую її, перш ніж вони зможуть її побачити. Як ви можете собі уявити, якщо вони помиляються, їм потрібно це зробити ще раз.
krolth

@krolth Це велика справа, щоб ваші артисти отримали VS Express та XNA як частину налаштування їх на роботу над проектом? Я думаю, що в цей момент компроміс з необхідністю написати керівництво та допомогти людям через нього набагато перевищить продуктивність, яку ви втрачаєте зараз, оскільки художники не можуть бачити їхню роботу в двигуні. Щоб упорядкувати процес, надайте їм файл .BAT, щоб вони могли двічі клацнути, щоб перекомпілювати все, не відкриваючи IDE. І якщо вони працюють тільки з ОС X, ну, жорстке лайно. Ласкаво просимо до гри Dev. Вони можуть здійснити свою справу і чекати наступних скоєних XNB.
michael.bartnett

це не така велика справа, просто біль. Але я думаю, це доведеться робити. Дякую всім за відповіді / коментарі!
krolth

1

Я продовжував це розслідувати і опублікую це на користь того, хто має те саме питання.

Вірна відповідь на це полягає в тому, щоб пропустити ContentPipeline і використовувати Texture2D.FromStream для завантаження текстур під час виконання. Цей метод відмінно працює на ПК і навіть якщо буде невелика продуктивність хіта це те , що я можу оптимізувати коли я ближче до дати релізу.

Наразі мені потрібна можливість динамічно змінювати контент як для редактора, так і для гри саме те, що мені потрібно. Як тільки вміст буде заморожено, я можу оптимізувати це, повернувшись до ContentPipeline.


Ви перевірили це правильно? З мого досвіду Texture2D.FromStreamсамо по собі мало. Причиною цього є те, що оскільки версія 4 XNA працює з попередньо розмноженими альфа-текстурами, і хоча контент-конвеєр автоматично опікується цією обробкою для вас, Texture2D.FromStreamце не означає, що ви, мабуть, зіткнетеся з проблемами, коли малюєте спрайти з прозорістю. Я можу розмістити робоче рішення, якщо хочете.
Девід Гувейя

Крім того, Texture2D.FromStreamне підтримує завантаження .BMPфайлів у той час як контент конвеєра. Це те, що, ймовірно, може скинути вас, якщо ви раніше використовували будь-які .BMPактиви, а потім переходили на Texture2D.FromStream. У мене також є рішення щодо цього обмеження. Я просто продовжу і розміщу його.
Девід Гувейя

0

Перевірте цей проект .

Це дозволить вашому виконавцю створити XNB майже з усього, що підтримує конвеєр контенту XNA за замовчуванням. Перерозподіл фреймворків XNA все ще потрібен, хоча виконавцю Visual Studio не потрібен.


Дякуємо за вказівник. Дивлячись на код, здається, що я змінив зразок Microsoft, на який я посилався. Це залежить від того, щоб встановити повну XNA Game Studio (див. ContentBuilder.cs). Чому, на вашу думку, це не так?
krolth

Я не думаю, що це не так. Якщо ви хочете використовувати контент-конвеєр, тоді вам потрібно мати повну ігрову студію. Однак проект не заважає вашим художникам користуватися Visual Studio. Єдина інша альтернатива - це переписати контент-конвеєр.
ClassicThunder
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.