Я задаю этот вопрос, потому что я не нашел однозначного ответа на него.
Позвольте мне прежде всего высказать несколько вещей об игре и о том, что я уже сделал. Игра станет RTS-сетом в процедурном мире с использованием симплексного шума. Мир состоит из фрагментов размером 16 x 16, созданных из спрайтов размером 64 x 64. Мне удалось динамически загружать и выгружать фрагменты, что прекрасно работает. Мир будет немного похож на Rimworld, поэтому сверху вниз расположены различные слои спрайтов (сначала ландшафт, спрайты перехода, деревья, наклейки и т. Д.). Вновь созданные миры могут содержать сущности, которые могут влиять на окружающую среду (например, деревня, ставшая городом) и тем самым кусок. Я уверен, что это можно рассчитать с помощью какой-то функции, но это то, на что нужно обратить внимание.
Основной вопрос у меня есть, когда я уменьшить, все больше и больше плиток нарисованы , которые сильно влияют на производительность. При примерно 30000 спрайтах секция рисования занимает 8 мс, что составляет половину от того, что требуется для работы при 60 FPS. И это только местность. Я использую атласы текстур, чтобы ограничить количество отрисовок (30000 спрайтов, нарисованных за 6 отсчетов).
Целью является , чтобы иметь возможность отдалить города / села / города уровень всего пути , чтобы быть в состоянии увидеть всю страну. Это имеет быть сделано динамически (например, не нажав на иконку миникарты, а просто прокрутить назад так же , как в Supreme Commander).
Я прочитал много статей по этой проблеме, но я не нашел и не видел четкого примера того, как это будет работать. Вот список методов, которые я нашел, которые должны работать:
- Грязные прямоугольники, как описано здесь , где вы рисуете только новые вещи, а остальное оставляете в буфере. Это имеет большой смысл, но я не знаю, как реализовать это в Monogame.
- Мой предпочтительный выбор: широко использовать RenderTargets, как описано здесь , где вы рисуете в RenderTarget, а затем сохраняете его как текстуру. В моем случае блок 16 x 16, состоящий из 64 x 64, создал бы текстуру 1024 x 1024. Я действительно сомневаюсь, что это будет работать с точки зрения производительности, но результат будет состоять из высокодетализированных текстур, а также будет полезен для использования, учитывая тот факт, что большинство из них статические (рельеф / деревья и т. Д.) И не меняются так сильно. Но это также означает, что каждый раз, когда вносятся изменения в чанк, необходимо изменять Texture2D с помощью SetData, что, как я понял, довольно сильно загружает процессор. Однако, если бы текстуры были 16 х 16, они могут действительно работать, а также уменьшат использование памяти и диска.
- Наклоните текстуры, указав SourceRectangle в SpriteBatch. Для огромных лугов / океанов это плюс, так как рисуется только один спрайт. Однако для детализированной местности с разными цветами и разными спрайтами (биомы и биомы) я боюсь, что это не будет иметь большого значения.
- Мое собственное решение, которое ставит под угрозу детализацию, состояло в том, чтобы использовать стандартную белую плитку размером 64 x 64, придать ей цвет окружающих 4 плиток и затем масштабировать их так, чтобы они покрывали 4 предыдущих плитки. Различие здесь (помимо плитки, имеющей простой цвет) в том, что ландшафт заметно изменился. Я должен также упомянуть, что леса все еще должны быть нарисованы индивидуально, так как они не идеально квадратные.
Если у кого-то есть идеи о том, как решить эту проблему, даже если это означает компрометацию определенных вещей (таких как детализация или использование 16 x 16 спрайтов), я бы с удовольствием это услышал.
Ответы:
Графические карты оптимизированы для рисования нескольких вещей много раз, а не наоборот.
В вашем случае у вас есть много вещей (разных текстур), которые вы хотите рисовать много раз (количество плиток).
IMO, простейшая оптимизация, которую вы можете сделать, чтобы получить значительный прирост производительности:
Я бы порекомендовал делать обе вещи. Удачи.
источник
Я обнаружил, что SpriteBatch не подходит для рисования плиток. Одна из причин заключается в том, что спрайты предназначены для динамических объектов и используются для нескольких целей. Другая причина в том, что он невероятно загружен процессором , например. как объяснено в описании чертежа, 30 000 объектов стоят 8 мс (в то время как мой набор микросхем увеличен до 30%). Кроме того, до 3000 спрайтов может быть отрисовано до того, как новый вызов отрисовки должен быть сделан на графический процессор (пакетный и все).
Решением было нарисовать мои собственные плитки, используя текстурированные квадраты . Это в сочетании с VertexBuffer позволило мне рисовать до 500 000 текстурированных плиток за один вызов, когда метод рисования занимал примерно 1/20 миллисекунды. Конечно, мне, вероятно, не придется рисовать так много, но в любом случае я получил, чтобы мой GPU имел нагрузку 75% при стабильных 60 кадрах в секунду.
источник