Тут мы немного рассмотрим антиальясинг (AntiAliasing) а конкретнее его частную реализацию мультисемплинг (MultiSampling). Я не буду вдаваться в детали теории, математические обоснования и понятия. Я же сразу перейду к практической стороне вопроса, ибо лучше один раз увидеть, чем…
Итак создаем новый проект Windows Game и чтобы не терять времени на решение рутинных задач в Solution Explorer добавьте в проект класс Camera из архива с ресурсами к статье, данный класс полностью реализует функционал 3D камеры и готов к использованию. В классе игры объявите экземпляр класса камеры
1
private Camera camera;
А в методе Initialize() иницализируйте его и добавьте в компоненты нашего проекта
1
2
3
4
5
6
7
8
protectedoverridevoid Initialize(){ camera = Camera(this); Components.Add(camera);base.Initialize();}
При вызове конструктора без дополнительных параметров камера распологается в пространстве в координатах 0,0,10 и направлена в центр координат 0,0,0. Управление камерой клавишами WASD, вращение мышкой.
Двигаемся дальше, в подпроекте Content добавьте папку Models и добавьте в нее модель AK74U.FBX. Это модель автомата которую я скачал с TurboSquid и сконвертировал при помощи 3DS MAX, на ней-то мы и будем рассматривать альясинг. Теперь надо нарисовать нашу модель.
Как видите орисовка идет при помощи BasicEffect без лишних усложнений, матрицы вида и проекции беруться из объекта камеры, мировая же матрица расчитывается на основе местоположеня модели и ее масштабирования. Теперь в методе Draw вызываем на отрисовку наш автомат
1
2
3
4
5
6
7
protectedoverridevoid Draw(GameTime gameTime){ GraphicsDevice.Clear(Color.CornflowerBlue);DrawModel(modelAK74U, new Vector3(0f, 0f, -20f), Matrix.CreateScale(0.05f));base.Draw(gameTime);}
Япоместил модель автомата немного «назад» и уменьшил ее масштаб, т.к. модель получилась довольно большой.
Прежде чем запустить приложение в методе Update(GameTime gameTime) добавьте следущий код, иначе не сможете выйти из приложения кроме как по Alt+F4.
Запускаем приложение и любуемся автоматом, обратите внимание на приклад автомата, а точнее «лесенку» которой он отрисовывается – это и есть эффект альясинга с которым мы сейчас и будем бороться.
Для начала напишем один вспомогательный метод, который будет получать массив элементов перечисления (enum).
Добавьте в проект новый класс Helpers и добавьте в него пространство имен using System.Reflection; далее метод который будет возвращать массив элементов перечисления
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
publicstatic T[] GetEnumValues<T>(){if(!typeof(T).IsEnum){return null;} FieldInfo[] fields =typeof(T).GetFields(BindingFlags.Static| BindingFlags.Public); T[] values = T[fields.Length];for(int i =0; i < fields.Length; i++){ values[i]=(T)fields[i].GetValue(null);}return values;}
Технология reflection конечно не отличается производительносью, с другой стороны мы могли бы воспользоваться статичным методом GetValues класса Enum, он возвращает массив объектов типа Object, а при конвертации значимого типа в ссылочный и обратно производятся операции boxing/unboxing (упаковка/распаковка), что в свою очередь тоже не есть хорошо.
Теперь собственно включаем мультисемплинг (антиальясинг) и подписываемся на событе которое будет срабатывать в момент подготовки графического устройства к созданию, где мы можем управлять параметрами создания устройства. В методе Initialize()пишем следующий код
Теперь напишем обработчик события подготовки графического устройства
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
privatevoid graphics_PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e){// получаем массив типов антиальясинга MultiSampleType[] types = Helpers.GetEnumValues<MultiSampleType>(); GraphicsAdapter adapter = e.GraphicsDeviceInformation.Adapter;// обходим массив в обратном порядке с наибольшего и проверяем возможности видеокарты по // поддержке данного типа сглаживанияfor(int i = types.Length-1; i >=0; i--){if(adapter.CheckDeviceMultiSampleType(DeviceType.Hardware, adapter.CurrentDisplayMode.Format, false, types[i])){ e.GraphicsDeviceInformation.PresentationParameters.MultiSampleQuality=0; e.GraphicsDeviceInformation.PresentationParameters.MultiSampleType= types[i]; break;}}}
Запускаем приложение. Моя текущая видеокарта поддерживает четырехкратный антиальясинг, но уже на таком уровне заметно значительное улучшение картинки.
Должен предупредить операция антиальясинга не является бесплатной, на тяжелых сценах может наблюдаться значительное замедление визуализации. В современных играх хорошим тоном считается позволить пользователю самому указать уровень мультисамплинга.