Я занимаюсь разработкой 2D-игры, и у меня много спрайтов. Я использовал 3D-анимацию и модели для рендеринга в 2D, чтобы придать им «Fallout» или «Diablo». Это также проще, чем рисовать от руки, смеется.
Мне уже приходилось снижать частоту кадров до 15 кадров в секунду, что было самым низким значением, которое я мог опустить, чтобы они не выглядели прерывисто. Однако было грустно из-за того, как выглядели невероятно плавные 24 кадра.
Я сделал это по двум причинам:
1) Сократить пространство на жестком диске. Чем меньше изображений, тем меньше будет моя общая игра.
2) Сократить потребление оперативной памяти. Чем меньше изображений загружается, тем больше у меня шансов избежать проблем, связанных с ограничением моего объема оперативной памяти.
Однако, если бы был способ сжать изображения как на жестком диске, так и в оперативной памяти, я бы так и сделал. Я проверял это раньше, и большинство из них не получают никаких изменений в качестве при передаче из RGBA8888 в RGBA5555 и лишь небольшое попадание при преобразовании в RGBA4444 в моей программе TexturePacker. Я не делаю этого в настоящее время, потому что SFML, похоже, использует один и тот же объем памяти независимо от того, какой это тип изображения .PNG. Я изучал, как загрузить его по-другому, но не смог найти ничего по этому вопросу.
Я много читал о том, как работать с 2D-видеоиграми. Консенсус ошеломляет: упакуйте свои спрайты в более крупную текстуру для отличной производительности! Поэтому я упаковываю свои крошечные спрайты в гораздо большую таблицу спрайтов, используя TexturePacker.
Тем не менее, я планирую иметь 10-15 анимаций на персонажа, 5 направлений для перемещения и 15-40 кадров на анимацию (вероятно, в среднем 24). 15 анимаций, 5 направлений и в среднем 24 кадра на анимацию; Это 1800 отдельных кадров на символ. Если упаковано в спрайт лист, то это всего 75 изображений. (Один лист спрайтов на Анимацию, на Направление. 15 * 5)
Для одного персонажа с огромным боссом в игре я не могу использовать таблицу спрайтов и должен запрограммировать способ простой загрузки одного изображения за раз. Я не знаю, смогу ли я сделать это для производительности еще.
Для персонажей я уже упаковал их в таблицу спрайтов. Для одного ходящего персонажа это работает большую часть времени, хотя иногда и останавливается. Однако я приписываю это моему плохо продуманному коду, который заменяет текстуры вместо предварительной загрузки всех текстур для этого символа.
Если бы я должен был предварительно загрузить текстуры, это имеет смысл для спрайтов. Я только предположил бы, что это плохая идея предварительно загрузить 1800 крошечных изображений для каждого персонажа.
Тем не менее, я думаю, что потоковая передача их в память и из памяти по одному будет чрезвычайно быстрой, поэтому мне нужно было бы иметь только одно изображение в памяти за один раз. Разве это не значит, что в любой данный момент каждый персонаж потребляет всего несколько КБ вместо 45 + МБ?
Я полагаю, что это убило бы мою производительность, поскольку потоковая передача должна была бы быть невероятно быстрой (15 изображений входили и выходили из памяти и рендеринга в секунду), и хотя изображения были бы очень маленькими - возможно, было бы лучше загрузить символьные спрайт-листы в память вместо. Но мне все равно придется кодировать систему рендеринга в виде одного изображения для моего более крупного персонажа.
Я экспериментировал, но это не простой процесс. Особенно учитывая тот факт, что я работаю над другими частями игрового движка, которые сейчас не связаны с графикой.
Ответы:
У нас похожий случай с нашим RTS Remake. Все юниты и дома являются спрайтами. У нас есть 18 000 спрайтов для юнитов, домов и местности, плюс еще ~ 6 000 для командных цветов (в качестве масок). Длинно растянутые у нас также есть около 30 000 символов, используемых в шрифтах.
Итак, главная причина атласов:
Что не сработало у нас:
Теперь у нас есть все, что упаковано в несколько десятков атласов 1024x1024 (современные графические процессоры поддерживают еще большие размеры), и это прекрасно работает, потребляя всего ~ 300 МБ памяти, что вполне подходит для игр для ПК. Некоторые оптимизации у нас были:
Когда вы серьезно подумываете о переходе на мобильные устройства, вы будете беспокоиться об ограничениях. А пока просто включите игру и привлекайте игроков! ;)
источник
У меня есть тангенциально связанный ответ в здесь , но общая идея состоит в том, что, если вы загружаете и рисования текстур в разное время (вы не загружая дополнительные текстуры в то время как вы будете рендеринга), то есть два места , где то , что вам do повлияет на вашу производительность:
Время загрузки:
Это момент, когда вы загружаете свои текстуры в память. Весь объем данных , которые вы отправляете VRAM, что будет в основном определять , как долго будет ваше время загрузки. Создание текстур меньшего формата, таких как RGBA4444, сделает это быстрее. Однако, если вы не загружаете текстуры в сотни мегабайт в VRAM, у вас, вероятно, не будет узкого места здесь. Если вы это сделаете, хороший экран загрузки может облегчить ожидание.
Объединение ваших текстур в атласы будет малоэффективным, так как весь объем информации, отправляемой вами в VRAM, будет одинаковым. На самом деле, если вы размещаете свои текстуры и вам нужно оставлять пустые места в ваших атласах, то вы фактически будете отправлять больше данных в VRAM, и поэтому эта часть будет работать медленнее!
Производительность рендеринга:
Как только все ваши текстуры будут в VRAM, количество имеющихся у вас текстур не повлияет на производительность рендеринга. Есть четыре элемента, которые влияют на производительность рендеринга:
Изменения состояния рендеринга : каждый раз, когда вы меняете изображение, с которого вы хотите рендерить, серьезно увеличивается время, необходимое для его рендеринга. В общем, вы хотите минимизировать количество изменений состояния, и вы можете уменьшить количество изменений состояния, сгруппировав несколько изображений, которые вы будете последовательно рисовать, в атлас текстуры.
Просто atlasing недостаточно. Вы должны атлас таким образом, чтобы изменения состояния были уменьшены, чтобы получить прирост производительности. Например, можно подумать, что наличие вашего главного героя в листе спрайтов даст вам прирост производительности, но если вы рисуете только один спрайт из этого листа спрайтов на кадр, вы не получите никакого выигрыша в производительности по сравнению с каждый спрайт в отдельном файле.
Правильная атлизация не тривиальна, но в целом вы можете безопасно группировать спрайты из одного слоя. Например, наличие всех элементов графического интерфейса на одном листе спрайтов является очень многообещающей идеей, в то время как группировка монстров по алфавиту может и не быть.
Тиражные звонки: В общем, ты можешь хотеть свести к минимуму количество твоих звонков. Хорошее практическое правило заключается в том, что если между двумя вызовами отрисовки нет изменений состояния рендеринга, вы можете объединить их в один вызов отрисовки. Для более высокого прироста производительности вы можете использовать, скажем, 8 текстурных сэмплеров и групповые вызовы рисования для каждых 8 текстур, так что вам нужно только менять текстуры каждые 8 текстур.
Количество треугольников: на самом деле, чем больше треугольников вы рисуете, тем больше времени уходит на их рисование. Тем не менее, в современных компьютерах и для большинства 2D-игр вы будете очень далеки от этого. Вы можете безопасно рисовать сотни тысяч спрайтов за кадр и при этом получать безумно хорошие частоты кадров. Вероятно, вы будете более загружены процессором, если будете рисовать огромное количество спрайтов до того, как у вас возникнут проблемы с вашим графическим процессором.
Настройки API: Если вы все делаете правильно, и у вас все еще странно низкая частота кадров, проверьте настройки, с которыми вы рисуете свои спрайты. Я не знаю SFML, но, например, в Direct3D 9 создание буфера вершин с
D3DUSAGE_DYNAMIC
или вD3DPOOL_MANAGED
может легко увеличить время рендеринга в десять раз. Конечно, использование vSync ограничит частоту кадров при частоте обновления вашего монитора. Кроме того, использование невыровненных FVF может снизить производительность в некоторых графических процессорах. Это тоже для Direct3D 9.В вашем случае, проверьте документацию для API, который вы используете.
Если у вас есть только небольшое или среднее количество текстур (менее 1 ГБ), и вы рисуете небольшое количество спрайтов (менее миллиона на кадр), то первое, на что я бы посмотрел, это изменение настроек API, и затем уменьшить количество состояний рендеринга и отрисовки вызовов.
источник