
- •Содержание
- •Очистка буферов графического устройства
- •Избирательная очистка буферов
- •Устранение скрытых дефектов приложения
- •Общие сведения о примитивах
- •Введение в hlsl
- •Типы данных hlsl
- •Функции и семантики hlsl
- •Техники, проходы и профили hlsl
- •IncludeHandler – объект, используемый для обработки директив #include в fx-файле. Так как наш файл не содержит директив #include, мы будем использовать значение null
- •Визуализация объекта, использующего эффект
- •Запускающее приложение
Общие сведения о примитивах
Примитивом называется графический объект - точка, прямая линия, треугольник, которые используются для построения более сложных объектов. В XNA Framework поддерживает шесть типов примитивов, заданных структурой PrimitiveType: список точек PointList, список линий LineList, полоса линий LineStrip, список треугольников TriangleList, полоса треугольников TriangleStrip и веер треугольников TriangleFan.
Примитивы описываются координатами точек вершин в мировой системе координат. В XNA и OpenGLиспользуется правая система мировых координат, а в DirectX - левая. Начало мировой системы координат находится на поверхности экрана в его центре. Для наблюдателя, смотрящего на экран, ось Ox направлена по горизонтали вправо, а ось Oy - по вертикали вверх. Системы отличаются только направлением оси Oz: в правой системе координат она направлена из глубины экрана к пользователю, а в левой - от пользователя в глубину экрана.
Совокупность трехмерных объектов в мировой системе координат называется сценой. Визуализация сцены выполняется при помощи установки камеры, размещение которой также задается относительно мировой системы координат. Положение камеры ассоциируется с положением глаз наблюдателя и с математической точки зрения определяет матрицу вида. Для корректного отображения объектов сцены на экране каждый из них предварительно преобразуется матрицей вида. Обычно камера отодвигается от экрана в положительном направлении оси Oz и несколько приподнимается вверх в положительном направлении оси Oy. Это позволяет установить взгляд наблюдателя на сцену как с балкона театра.
В пространстве имен Microsoft.Xna.Framework.Graphics имеется ряд структур для хранения информации о вершинах примитива. В данном упражнении мы будем использовать структуру VertexPositionColor, инкапсулирующую информацию о координатах и цвете вершины.
Напомним, что любая структура, как и класс, содержит члены-методы и члены-данные и относится к значимому типу (в противоположность кссылочномы типу). Члены-данные струтуры (как и класса) называются полями. В структурах C# конструктор по умолчанию является предопределенным и его задавать нельзя. Это сделано для того, что объявление структурной переменной одновременно означает и создание экземпляра структуры с неявным вызовом конструктора по умолчанию. Зато параметризованных конструкторов может быть сколько угодно при условии, что каждый из них имеет уникальную в рамках структуры сигнатуру. В этом случае применение оператора new обязательно.
Библиотечная структура VertexPositionColor имеет один параметризованный конструктор вида:
public VertexPositionColor(Microsoft.Xna.Framework.Vector3 position,
Microsoft.Xna.Framework.Graphics.Color color)
position - координаты вершины
color - цвет вершины
Информацию обо всех вершинах примитива можно хранить в массиве, например:
VertexPositionColor[] vertices;
Но здесь есть один нюанс. Дело в том, что при визуализации примитивов информация о вершинах напрямую передается в графический процессор видеокарты GPU (Graphics Processor Unit), который не знает, что используется массив структур именно VertexPositionColor. Для разъяснения графическому процессору формата отдельных полей структуры применяются декларации формата вершины. В XNA Framework декларация вершины задается классом VertexDeclaration, конструктор которого имеет вид:
public VertexDeclaration(Microsoft.Xna.Framework.Graphics.GraphicsDevice graphicsDevice,
Microsoft.Xna.Framework.Graphics.VertexElement[] elements)
graphicsDevice - графическое устройство, используемое для работы с вершинами
elements - массив элементов c описанием формата
Массив elements содержит информацию о формате данных, с которыми будет работать графическое устройство:
Адрес описываемого поля структуры (смещение от начала структуры)
Тип поля структуры (скаляр, вектор, упакованный вектор)
Информация, содержащаяся в данном поле (координаты вершины, цвет вершины, текстурные координаты и т.п.)
Некоторая другая служебная информация
Если для хранения данных применяется структура VertexPositionColor, то описание ее формата хранится в статическом поле только для чтенияVertexPositionColor.VertexElements. Пользователю (программисту) остается только передать это поле конструктору класса VertexDeclaration в качестве второго параметра.
Состав элементов сцены описывается один раз при загрузке приложения. Код загрузки описания примитивов можно разместить, например, в обработчике события Load формы. Изменение позиции объектов и их цвет, расчитываемые для каждого кадра визуализации сцены с помощью мировых матриц смещения, поворота и масштабирования, матриц проекций и вида, помещают в блок кода Update(), который выполняется каждый раз в обработчике события Paint.
Визуализация массива примитивов осуществляется с помощью метода класса GraphicsDevice, имеющего следующее описание
public void DrawUserPrimitives<T>(Microsoft.Xna.Framework.Graphics.PrimitiveType primitiveType, T[] vertexData,
int vertexOffset, int primitiveCount)
T - шаблон типа
primitiveType - тип примитива, задаваемый с использованием перечисления PrimitiveType
vertexData - массив вершин примитива
vertexOffset - смещение от начала массива. Данный параметр обычно равен нулю. Ненулевые значения применяется, когда визуализируемый примитив использует примитивы лишь из части массива (например, вершины разных примитивов хранятся в одном большом общем массиве)
primitiveCount - количество примитивов, которые нужно выбрать для визуализации
Таким образом, для визуализации примитивов приложение должно выполнить примерно следующие шаги:
В обработчике события Load:
Создать экземпляр presentParams класса PresentationParameters и определить в его свойствах настройки будущего графического устройстваdevice
Создать само графическое устройство device типа GraphicsDevice и настроить его через свойства экземпляра presentParams
Создать и заполнить массив vertices структур типа VertexPositionColor[], где каждый элемент этого массива задает координаты вершины типаVector3 и ее цвет типа Color
Создать декларацию формата вершины - экземпляр decl структуры VertexDeclaration, передав ее конструктору статическое поле-массивVertexPositionColor.VertexElements
В обработчике события Paint:
Передать ссылку на объект decl свойству VertexDeclaration объекта device для корректной обработки вершин при отображении сцены на экране
Привести размеры заднего буфера в соответствие размерам окна вывода
Очисть экран методом device.Clear()
Нарисовать набор примитивов вызовом метода device.DrawUserPrimitives()
Показать полученное изображение на экране, переключив буферы методом device.Present()
На первый взгляд операцию передачи ссылки на объект decl свойству VertexDeclaration объекта device было бы рациональнее вынести в обработчик события Load. Однако настройки графического устройства теряются при сбросе методом Reset() и нужно восстанавливать информацией из decl иpresentParams. И это нужно делать сразу в обработчике события Paint.
Но это еще не все. Дело в том, что все современные видеокарты содержат специализированные GPU - векторные и пиксельные процессоры, используемые для ускорения операций преобразования вершин и закраски примитивов. Так как эти процессоры принимают участие при визуализации любых примитивов, приложение должно запрограммировать их на выполнения требуемых преобразований. Если этого не сделать, то результат вызова метода device.DrawUserPrimitives() будет непредсказуемым. Отсюда возникает необходимость программирования вершинных и пиксельных процессоров графического ускорителя видеокарты.