Игра на C # или C ++: в память загружено много 16 цветных изображений.Эффективное решение? - PullRequest
10 голосов
/ 03 января 2011

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

Справочная информация:
- Все еще обсуждают, использовать ли C # (XNA) или C ++. Мы не хотим брать на себя обязательства, пока не выясним, как решить эту проблему на обоих языках.
- Если возможно, было бы полезно использовать максимум 256 МБ ОЗУ. - Два персонажа будут присутствовать одновременно, и эти персонажи могут меняться только между битвами. Есть время для загрузки / освобождения памяти между битвами, но игра должна работать с постоянной скоростью 60 кадров в секунду во время боя. Каждый кадр составляет 16,67 мс
- Общее количество изображений на одного персонажа исчисляется сотнями. Каждое изображение размером примерно 200x400 пикселей. В любой момент будет отображаться только одно изображение от каждого персонажа.

Несжатый, каждое изображение занимает примерно 300 КБ из моих расчетов; свыше 100 МБ для всего персонажа. Это слишком близко к пределу в 256 МБ, учитывая, что память потребуется и для некоторых других ресурсов.

Так как каждое изображение может быть сделано в общей сложности 16 цветов. Теоретически я должен быть в состоянии использовать 1/8 места, если я могу воспользоваться этим. Я осмотрелся, но не нашел ни слова о поддержке палитровых изображений. (Сохранение каждого пикселя с использованием меньшего количества битов, каждый из которых соответствует 32-битному цвету RGBa)

Мы пытались использовать сжатие DXT, однако артефакты сжатия довольно заметны.

Я собирался создать свой собственный формат файла с 4 битами на пиксель (и некоторой дополнительной информацией о палитре), загрузить все изображения этого нового формата в оперативную память перед битвой, а затем при рисовании любого конкретного изображения распаковать только это изображение необработанное изображение, чтобы его можно было правильно отобразить. Я не знаю, реалистично ли выполнять так много операций присваивания (приблизительно 200x400 для каждого символа = 160k) для каждого кадра. Это звучит очень нахально для меня.

Есть ли у кого-нибудь совет о том, звучит ли мое решение разумным, и если есть, возможно, лучшее решение?

Большое спасибо!

(Я также попытался использовать изображение только с 1 каналом, а затем с помощью шейдера выполнить серию операторов if для перевода различных значений в другие цвета. К сожалению, для шейдера было слишком много строк кода. также довольно хакерский и плохо масштабируется.)

Ответы [ 5 ]

3 голосов
/ 03 января 2011

Используйте взамен S3 Texture Compression (он же DXTn). S3TC позволяет хранить текстуры с разрешением 4 бит / пиксель или 8 бит / пиксель, и изначально поддерживается графическими картами. Вам не нужно беспокоиться о распаковке на лету, так как видеокарта делает это.

DirectX имеет очень хорошую поддержку S3TC, как на C ++, так и на C #.

2 голосов
/ 03 января 2011

Если вы хотите нацелиться на XBox 360 и не иметь надлежащего (полноценного) devkit, тогда C # - ваш единственный вариант. Когда вы запускаете XNA, вам, безусловно, становится намного проще, особенно если вы сейчас занимаетесь 2D (и заботитесь о многих других вещах, о которых вам сейчас не нужно беспокоиться).

Что касается проблемы с ограничением памяти, предложите ее устранить:

  • Используйте формат текстуры 1555, чтобы уменьшить размер в два раза (хотя у вас будет только 1 бит альфа) * ​​1006 *
  • Есть ли на разных изображениях общие разделы? Могли бы вы визуализировать персонажа, используя несколько маленьких плиток, а не одну большую (то есть сетку размером 2х4 или больше). Скорее всего, у вас будет много пустого пространства в углах, которое можно разделить между большинством изображений, и это даст хорошую экономию (я только что заметил, что кто-то уже упоминал об этом через спрайт-листы - хотя это должен быть вариант сохранения без потерь память).
  • Вы упоминаете, что уже пытались подделать паллетизированные текстуры. Вместо операторов IF вы могли бы иметь вторую текстуру, которая содержит цвета палитры, и использовать значение, полученное из первой текстуры, в качестве координаты текстуры, чтобы искать в 2-ю текстуру с помощью пиксельного шейдера (2-я текстура - это только 1-мерная). текстура из 32-битных значений цвета).
  • Учитывая мощь современных процессоров и в зависимости от того, что еще вы делаете в то время, у вас вполне может быть достаточно свободных ресурсов, чтобы распаковывать кадры на лету для двух символов в текстуры, готовые для рендеринга (особенно с многоядерными процессорами). Вам нужно будет по крайней мере дважды буферизовать текстуры, чтобы остановить блокировку ЦП, ожидая, пока графический процессор завершит их использование из предыдущего кадра.

Вы также можете комбинировать некоторые из этих параметров, чтобы сохранить больше.

1 голос
/ 03 января 2011

Вы можете использовать дерево кодирования Хаффмана для хранения сжатых данных в памяти (поскольку, как вы говорите, оно хорошо сжимается);затем извлечь / загрузить в режиме реального времени.Есть и другие сжатые структуры данных, которые вы можете использовать.

1 голос
/ 03 января 2011

Я думаю, что размещение ваших изображений в таблице спрайтов - ваш лучший вариант.Это дает вам наилучший баланс между потерей данных изображения на сжатие и стоимостью памяти.

Я бы начал с C # и платформы XNA, поскольку имеется отличная поддержка встроенного процессора спрайтов, а конвейер контента может автоматическиконвертировать отдельные изображения в полную таблицу спрайтов во время компиляции.Microsoft предоставляет пример проекта, демонстрирующий эту функциональность здесь: http://create.msdn.com/en-US/education/catalog/sample/sprite_sheet

0 голосов
/ 03 января 2011

Вы можете посмотреть на xnaMUGEN . Движок для файтингов - это то, что легко сделать в C #.

...