Навигация
· XNA FAQ
· С чего начать
· Конкурсы
· Обратная связь
· XNA Блоги
Сейчас на сайте
· Гостей: 1

· Пользователей: 0

· Всего пользователей: 3,684
· Новый пользователь: headron
Последние фото
Эх, чуть не проспал закрытие.
Эх, чуть не проспал ...
Альбом: XNA Engine

GB
GB
Альбом: XNA Engine

South Park Coon & Friends
South Park Coon & Fr...
Альбом: XNA Games

Блоги
yavshoke
» XboxOne - интерес...
dampirik
» Push уведомления ...
dampirik
» Реклама,статистик...
Chort
» XNA и StartCoroutine
Chort
» Curve Class
dampirik
» Реклама, статисти...
dampirik
» Увеличение скорос...
dampirik
» Реклама, статисти...
general
» Распаковка DxtCom...
general
» Как работать с XN...
Поддержка
microsoft.com
1gb.ru - Дом для вашего сайта
Статистика посещений:

Производительность при использовании класса SpriteBatch

Задача

При неправильном использовании класса SpriteBatch, ваше приложение будет выполняться ужасно медленно, если вы захотите отрисовывать большое количество изображений.

Решение

Как уже было упомянуто в разделе 3-1, создание нового класс SpriteBatch каждый фрейм или отдельный рендеринг каждого изображения (между вызовами методов Begin и End класса SpriteBatch) уничтожит вашу производительность. Но есть и более тонкие аспекты, о которых Вы должны знать.

Как это сделать

Оптимизация производительности: режимы cортировки спрайтов

Метод Begin класса SpriteBatch позволяет вам устанавливать SpriteSortMode. Но прежде, чем я подробно их опишу, вы должны знать, как вашей видеокарте нравится работать и конечно что она не любит.

Отрисовку двухмерного изображения на экран делают, рисуя два треугольника и накладывая на них текстуру. Вашей видеокарте нравится выводить огромное количество треугольников за раз, не прерываясь на вспомогательные операции. Однако, всякий раз, когда вы должны изменить текстуру, вы прерываете работу вашей видеокарты. Другими словами, отрисовка 100 изображений с одной текстурой пройдет намного быстрее, чем отрисовка 100 изображений каждое со своей текстурой. Это означает, что вы можете улучшить свою производительность, изменяя активную текстуру как можно реже.

Учитывая это, вы можете перейти к возможным режимам сортировки спрайтов, которые определяются как параметр в методе SpriteBatch.Begin:


Deferred: Это режим SpriteSortMode по умолчанию. Вы вряд ли захочется его использовать, поскольку в этом режиме фактически никакая сортировка не используется. Всякий раз, когда вы добавляете спрайт к пакету, вызывая метод SpriteBatch.Draw, спрайт просто размещается в вершине стека. Когда вы вызываете метод SpriteBatch.End, все спрайты в стеке рисуются в том порядке, в каком спрайты были помещены в стек.
Texture: Обычно, для оптимальной производительности и простоты, вы будете использовать этот режим. Когда вы вызываете метод SpriteBatch. End, все изображения, которые выпомещали в стек, сортируются по текстурам, прежде, чем XNA фактически попросит, чтобы ваша видеокарта их нарисовала. Таким образом, ваша видеокарта может рисовать все треугольники, использующие одинаковую текстуру в одном прогоне, и вы уменьшите число раз, когда вы должны прервать работу видеокарты, чтобы изменить текстуру. Однако, в случаях, когда вы используете альфа-прозрачность, это может вызвать проблемы, и вы можете захотеть использовать один из следующих режимов.


BackToFront: При использовании альфа-смешивания вы захотите объекты, которые являются ­самыми дальними рисоваться вначале. Чтобы понять почему, прочитайте предыдущий раздел. Для этого случая, метод SpriteBatch.Draw, который добавляет изображение к классу SpriteBatch, имеет перегрузку, которая принимает layerDepth. Используя это значение с плавающей точкой, вы можете определить, глубину сортировки спрайтов, где 1.0f указывает уровень, который является самым дальним (который будет, например, содержать вашу траву), и 0.0f указывает уровень, который является самым близким (в котором например находятся камни). Вы можете определить любое число промежуточных значений. При использовании режима BackToFront, всякий раз, когда вы вызываете метод SpriteBatch.End, изображения в SpriteBatch будут отсортированы так, что самый дальний уровень будет рисоваться сначала.


FrontToBack: Это противоположность предыдущего режима, при котором вначале рисуются самые близкие изображения. Поскольку каждый пиксел рисуемый на экране никогда не будет перезаписан (потому что последующие изображения находятся позади тех, которые рисуются впереди), это приводит к лучшей производительности. Однако, это не будет работать с альфа-смешиванием (см. предыдущий раздел), и даст большую производительность, только если все изображения используют одну и ту же самую текстуру! Если текстура должна меняться десять раз, чтобы отрисовать самый ближний уровень, ваша производительность будет намного хуже, чем при использовании режима Texture.


Immediate: В противоположность всем другим режимам, в этом режиме XNA не будет ожидать вызова метода SpriteBatch.End, чтобы отрисовать все изображения в классе SpriteBatch. Пока вы добавляете изображения, которые используют одну текстуру в SpriteBatch, вызывая SpriteBatch.Draw, SpriteBatch поместит их в стек. Однако, если вы попробуете отрисовать спрайт, который использует другую текстуру, спрайты в текущем стеке будут немедленно отрисованы.

При использовании первых четырех режимов, только при вызове SpriteBatch.End, спрайты будут отсортированы, состояния рендеринга установлены, а треугольники и текстуры отправятся видеокарте. Это позволяет вам использовать несколько объектов класса SpriteBatch и добавлять новые спрайты к ним в случайном порядке, или даже рисовать трехмерные объекты, используя их собственные состояния рендеринга.

Однако используя режим Immediate, состояния рендеринга будут установлены когда вы вызываете метод SpriteBatch.Begin, f спрайты будут предоставлены после вызова SpriteBatch. Draw. Это означает, что у вас есть возможность изменять состояния рендеринга! Таким образом, вы можете обратиться к большему количеству режимов альфа-смешивания или даже рисовать спрайты, используя пользовательский пиксельный шейдер! Однако, рисуя изображения с использованием режима Immediate, вы не должны использовать ничего больше, например, трехмерные объекты, потому что вы вероятно измените состояния рендеринга, делая так. Когда вы захотите продолжать рисовать спрайты с вашим SpriteBatch, состояния рендеринга не будут восстановлены, таким образом вы будете выводить спрайты, используя состояния рендеринга и пиксельный шейдер трехмерного объекта.

Оптимизация производительности: сохранение нескольких изображений в одном графическом файле

Как обсуждалось в предыдущем разделе, если вы хотите отрисовывать большое количество спрайтов, то ваша видеокарта должна менять активную текстуру как можно реже. SpriteSortingMode.Texture уже много помогает, но для реальной игры вы будете нуждаться в сотнях других изображений, которые заставят Вашу видеокарту переключаться сотни раз между текстурами, серьезно ее замедляя.

Правильным подходом может быть размещение изображений, которые несколько соотносятся друг с другом в одно большое изображение, как как показано слева на рисунке 3-4. Таким образом, вы должны использовать параметр sourceRectangle метода SpriteBatch.Draw, чтобы определить, какая часть большого изображения содержит изображение, которое вы фактически хотите нарисовать, как показано во фрагменте кода раздела 3-3.

В изображении, показанном на рисунке 3-4, каждое подизображение содержит 40х40 пикселов. Код примера 3-3 определяет несколько прямоугольников, которые указывают, где подизображения позиционированы в одном большом графическом файле. Определение одного из этих прямоугольников в третьем параметре в методе SpriteBatch.Draw заставит это подизображение отрисоваться на экране.

Использование нескольких SpriteBatches

Как вы видели до сих пор, SpriteBatch — очень сильный объект. Вы могли группировать изображения всей игры в отдельный SpriteBatch, сортировать их и легко отрисовывать на экране. Однако, есть случаи, когда вы возможно захотите использовать несколько классов SpriteBatch.

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

Вы хотите немного дыма позади механизмов плоскостей, медленно исчезновения, и конечно большого количества дыма в следе после ракет. Если вы представляете все эти изображения, используя отдельный SpriteBatch, у вас есть проблема: вы хотите, чтобы все изображения были отсортированы по текстурам, чтобы добиться оптимальной производительности. Однако, вы нуждаетесь в плоскостях и ракетах, которые будут рисовать сначала, таким образом после этого вы можете смешивать их со своими спрайтам дыма. Это потребовало бы, чтобы ваши спрайты были сортированы по их layerDepth!

Решение находится при использовании двух объектов класса SpriteBatch: planeBatch и smokeBatch. В начале вашего метода Draw вы вызываете метод Begin обоих классов SpriteBatch. Затем, для каждой плоскости или ракеты, вы добавляете изображение плоскости или ракеты к planeBatch и дым позади плоскости или ракеты к smokeBatch. PlaneBatch может быть сортирован по текстуре, и smokeBatch может быть сортирован с использованием метода BackToFront. После того, как все изображения будут добавлены к пакетам, вы сначала вызываете метод End planeBatch, который заставит все изображения плоскостей и ракет отсортироваться по текстурам, и они будут рисоваться на экран с хорошей производительностью. Затем, вы вызываете smokeBatch.End, который заставит спрайты дыма смешаться с изображением. Так, у вас есть оптимальная производительность для того, чтобы рисовать ваши плоскости, и в то же время происходит корректное смешивание!

Перевод раздела 3-4 из книги XNA 3.0 Game Programming Recipes: A Problem-Solution Approach.  Остальные переводы смотрите на сайте www.x-graph.ru

Комментарии
#1 | IIporpammep 31.10.2012 14:47:57
"Как уже было упомянуто в разделе 3-1" это перевод какой-то книги? если да, неплохо бы указать её название.
#2 | aklemen 31.10.2012 18:21:32
Указал название книги в конце статьи.
#3 | IGreench 01.11.2012 10:32:10
Полезная статья! Спасибо =)
Добавить комментарий
Пожалуйста, залогиньтесь для добавления комментария.
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Авторизация
Логин

Пароль



Вы не зарегистрированы?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Мини-чат
Вы должны авторизироваться, чтобы добавить сообщение.

27.08.2014
Я умею немного на asp.net + html и css

22.08.2014
на ASP mvc 3 есть пару проектов. Могу помочь, если нужно. Обидно, если закроется Frown

21.08.2014
я тоже ноль

21.08.2014
Я в вебе только с php занимался да и то на уровне чтоб работало.

21.08.2014
Я в вебе полный ноль…

21.08.2014
Переводить его надо, хоть на ту же азуру. И двиг менять на что-то современное. Если есть веб-разрабы - можем скооперироваться. Один делать не буду.

21.08.2014
не знаю всех нюансов по оплате и все хорошее когда нибудь заканчивается

21.08.2014
А что случилось?

21.08.2014
похоже сайт будет работать до 28го числа

09.08.2014
Апи пока не видел. Но есть приложение в магазине Live Lock Screen BETA, так что думаю скоро будет

08.08.2014
Я про API для Update1. На нем работает это

08.08.2014
А что именно нужно? Чтото и сейчас открыто http://msdn.micro.
...105).aspx

06.08.2014
Кто-нибудь слышал об открытии доступа к Lock Screen Api?

31.07.2014
VPDExpress на базе MVS 2012, ни в какую не ловит исключения. Даже если их сам создаешь. И всех так?

25.07.2014
С днем системного администратора причастных к этой профессии! По случаю - тортик от жены

RSS каналы сайта
XNA - Новости
XNA - Статьи
XNA - Форум
XNA - Галерея
XNA - Файлы
Время загрузки: 0,06 секунд 8,709,547 уникальных посетителей