Нанесем на стороны куба какие-нибудь рисунки. Это могут быть любые плоские bitmap -рисунки. Для текстурирования объектов в Direct3D используется понятие тексела (texel). Тексел - сокращенное название элемента текстуры или соответствующее значение цвета для каждого адреса в текстуре. Адресом в текстуре служат координаты левого верхнего угла прямоугольника текстуры (обычно 0,0) и правого нижнего угла (обычно 1, 1).
Для того, чтобы отобразить кубический объект с использованием текстурирования, нужно изменить вершинный формат объекта, а также данные, пересылаемые в графическую карту. Мы заменим компонент цвета вершин примитивов координатами текстуры. Для того, чтобы получить куб и цветным и текстурным, будем просто использовать текстуру для определения цвета каждого примитива.
На этом подготовительная часть задачи текстурирования сторон куба завершена и можно приступать к основной части.
private void vb_Created(object sender, EventArgs e) { // Определить внутреннюю ссылку на вершинный буфер VertexBuffer buffer = (VertexBuffer) sender; // Явное приведение типов // Создать локальный массив структур непреобразованных координат CustomVertex.PositionTextured[] verts = new CustomVertex.PositionTextured[36]; // Задать параметры аппроксимирующих треугольников verts[0] = new CustomVertex.PositionTextured(-1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[1] = new CustomVertex.PositionTextured(-1.0F, -1.0F, 1.0F, 0.0F, 1.0F); verts[2] = new CustomVertex.PositionTextured(1.0F, 1.0F, 1.0F, 1.0F, 0.0F); verts[3] = new CustomVertex.PositionTextured(-1.0F, -1.0F, 1.0F, 0.0F, 1.0F); verts[4] = new CustomVertex.PositionTextured(1.0F, -1.0F, 1.0F, 1.0F, 1.0F); verts[5] = new CustomVertex.PositionTextured(1.0F, 1.0F, 1.0F, 1.0F, 0.0F); verts[6] = new CustomVertex.PositionTextured(-1.0F, 1.0F, -1.0F, 0.0F, 0.0F); verts[7] = new CustomVertex.PositionTextured(1.0F, 1.0F, -1.0F, 1.0F, 0.0F); verts[8] = new CustomVertex.PositionTextured(-1.0F, -1.0F, -1.0F, 0.0F, 1.0F); verts[9] = new CustomVertex.PositionTextured(-1.0F, -1.0F, -1.0F, 0.0F, 1.0F); verts[10] = new CustomVertex.PositionTextured(1.0F, 1.0F, -1.0F, 1.0F, 0.0F); verts[11] = new CustomVertex.PositionTextured(1.0F, -1.0F, -1.0F, 1.0F, 1.0F); verts[12] = new CustomVertex.PositionTextured(-1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[13] = new CustomVertex.PositionTextured(1.0F, 1.0F, -1.0F, 1.0F, 1.0F); verts[14] = new CustomVertex.PositionTextured(-1.0F, 1.0F, -1.0F, 0.0F, 1.0F); verts[15] = new CustomVertex.PositionTextured(-1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[16] = new CustomVertex.PositionTextured(1.0F, 1.0F, 1.0F, 1.0F, 0.0F); verts[17] = new CustomVertex.PositionTextured(1.0F, 1.0F, -1.0F, 1.0F, 1.0F); verts[18] = new CustomVertex.PositionTextured(-1.0F, -1.0F, 1.0F, 0.0F, 0.0F); verts[19] = new CustomVertex.PositionTextured(-1.0F, -1.0F, -1.0F, 0.0F, 1.0F); verts[20] = new CustomVertex.PositionTextured(1.0F, -1.0F, -1.0F, 1.0F, 1.0F); verts[21] = new CustomVertex.PositionTextured(-1.0F, -1.0F, 1.0F, 0.0F, 0.0F); verts[22] = new CustomVertex.PositionTextured(1.0F, -1.0F, -1.0F, 1.0F, 1.0F); verts[23] = new CustomVertex.PositionTextured(1.0F, -1.0F, 1.0F, 1.0F, 0.0F); verts[24] = new CustomVertex.PositionTextured(-1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[25] = new CustomVertex.PositionTextured(-1.0F, -1.0F, -1.0F, 1.0F, 1.0F); verts[26] = new CustomVertex.PositionTextured(-1.0F, -1.0F, 1.0F, 1.0F, 0.0F); verts[27] = new CustomVertex.PositionTextured(-1.0F, 1.0F, -1.0F, 0.0F, 1.0F); verts[28] = new CustomVertex.PositionTextured(-1.0F, -1.0F, -1.0F, 1.0F, 1.0F); verts[29] = new CustomVertex.PositionTextured(-1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[30] = new CustomVertex.PositionTextured(1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[31] = new CustomVertex.PositionTextured(1.0F, -1.0F, 1.0F, 1.0F, 0.0F); verts[32] = new CustomVertex.PositionTextured(1.0F, -1.0F, -1.0F, 1.0F, 1.0F); verts[33] = new CustomVertex.PositionTextured(1.0F, 1.0F, -1.0F, 0.0F, 1.0F); verts[34] = new CustomVertex.PositionTextured(1.0F, 1.0F, 1.0F, 0.0F, 0.0F); verts[35] = new CustomVertex.PositionTextured(1.0F, -1.0F, -1.0F, 1.0F, 1.0F); // Заполнить вершинный буфер данными треугольников buffer.SetData(verts, 0, LockFlags.None); }Листинг 12.14. Координаты вершин текстурированных примитивов
При отображении каждая сторона куба будет включать текстуру целиком, то есть отображаться полностью в текстуре.
// Создать вершинный буфер vb = new VertexBuffer(typeof(CustomVertex.PositionTextured), 36, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionTextured.Format, Pool.Default);Листинг 12.15. Код создания вершинного буфера в функции InitializeGraphics()
// Установка камеры в сцену private void SetupCamera() { //Создание перспективы device.Transform.Projection = Matrix.PerspectiveFovLH( (float)Math.PI / 4, // Угол зрения равен 45 градусов // Форматное соотношение сторон (float)this.ClientSize.Width / (float)this.ClientSize.Height, 1.0F, // Ближний план 100.0F); // Дальний план //Добавление камеры device.Transform.View = Matrix.LookAtLH( new Vector3(0, 0, 5.0F), // Положение камеры new Vector3(), // Положение объекта текущее new Vector3(0, 1, 0)); // Направление камеры // Освещение device.RenderState.Lighting = false; // Не скрывать обратную сторону плоской фигуры // device.RenderState.CullMode = Cull.None; // Преобразование пространства для произвольных поворотов /* device.Transform.World = Matrix.RotationYawPitchRoll( angle / (float)Math.PI, angle / (float)Math.PI * 2.0F, angle / (float)Math.PI); */ if (flagRotate) angle += 0.02F; }Листинг 12.16. Код, который нужно вырезать, и приращение угла скорректировать
protected override void OnPaint(PaintEventArgs e) { // Очистить цветом клиентскую область формы device.Clear(ClearFlags.Target, System.Drawing.Color.CornflowerBlue, 1.0F, 0); // Вызов нашей функции установки камеры SetupCamera(); // Сформировать сцену с учетом параметров // "положение-нормаль-цвет" device.BeginScene(); // Установить формат обработки вершин при отображении device.VertexFormat = CustomVertex.PositionTextured.Format; // Нарисовать треугольник по данным из буфера device.SetStreamSource(0, vb, 0); // Преобразование пространства для произвольных поворотов device.Transform.World = Matrix.RotationYawPitchRoll( angle / (float)Math.PI, angle / (float)Math.PI * 2.0F, angle / (float)Math.PI); device.DrawPrimitives(PrimitiveType.TriangleList, 0, 12); device.EndScene(); // Показать буфер кадра device.Present(); // Принудительно перерисовать this.Invalidate(); }Листинг 12.17. Перенесенный код в функции OnPaint()
// Сформировать сцену с учетом параметров // "положение-нормаль-цвет" device.BeginScene(); // Установить формат обработки вершин при отображении device.VertexFormat = CustomVertex.PositionTextured.Format; // Нарисовать треугольник по данным из буфера device.SetStreamSource(0, vb, 0); // Преобразование пространства для произвольных поворотов device.Transform.World = Matrix.RotationYawPitchRoll( angle / (float)Math.PI, angle / (float)Math.PI * 2.0F, angle / (float)Math.PI); // Установка текстуры device.SetTexture(0, texture); device.DrawPrimitives(PrimitiveType.TriangleList, 0, 12); device.EndScene();Листинг 12.18. Установка текстуры рисования сторон в функции OnPaint()
Direct3D позволяет устанавливать до восьми типов текстур одновременно для примитива рисования. В данном коде мы устанавливаем первым параметром только одну текстуру с индексом 0. Второй параметр является ссылкой на текстуру, которую нужно еще создать. Для этого служит класс Microsoft.DirectX.Direct3D. Texture. Класс имеет четыре версии конструктора
Мы воспользуемся для создания текстуры предпоследней из приведенных версий. Данный конструктор имеет четыре параметра.
private Device device = null; private VertexBuffer vb = null; private Texture texture = null; public void InitializeGraphics() { .................................... }Листинг 12.19. Создание поля-ссылки класса Form3 на текстуру
private void vb_Created(object sender, EventArgs e) { .......................................... // Заполнить вершинный буфер данными треугольников buffer.SetData(verts, 0, LockFlags.None); // Создать объект текстуры Bitmap bmp = new Bitmap(this.GetType(), "12_16.bmp"); texture = new Texture(device, bmp, 0, Pool.Managed); }Листинг 12.20. Создание пула памяти для текстуры и загрузка в него рисунка
Здесь в качестве текстуры используется прилагаемый к описанию рисунок "12_16.bmp" из каталога Source данной лабораторной работы (вы можете создать свой рисунок в формате bmp ).