Спонсор: Microsoft
Опубликован: 08.07.2007 | Доступ: свободный | Студентов: 1360 / 139 | Оценка: 4.43 / 4.02 | Длительность: 13:47:00
Специальности: Программист
Лекция 5:

Построение отрезков. Спрайты и вывод текста и сцен в текстуру

< Лекция 4 || Лекция 5: 123 || Лекция 6 >

Вывод текста

Довольно часто возникает необходимость вывести на экран некоторый текст. Традиционно разработчики двумерных и трехмерных приложений для вывода информационных сообщений использовали следующий подход:

  1. Создание текстуры, содержащей все буквы алфавита и цифры;
  2. Определение для каждого символа в текстуре его положения, например, текстурные координаты;
  3. Когда было нужно выводить текст, создается прямоугольник, содержащий нужный символ;
  4. Устанавливаются нужные текстурные координаты, и производится вывод;
  5. Эти шаги повторяются для каждого выводимого символа.

Библиотека Direct3D предоставляет более простые возможности по отображению текста на экране. Как обычно, вначале мы должны объявить переменные интерфейсного типа.

C++ LPD3DXFONT font;
Pascal var font: ID3DXFont;

Следующий шаг – это создание самого шрифта с помощью функции D3DXCreateFont(). Данная функция имеет довольно много параметров создаваемого шрифта, но мы рассмотрим только самые необходимые. Первый параметр представляет собой ссылку на устройство вывода; второй параметр задает высоту букв шрифта (размер); третий параметр определяет ширину символов; четвертый параметр определяет, будет ли шрифт полужирным или обычным (это реализуется через предопределенные константы FW_NORMAL и FW_BOLD ); пятый аргумент определяет количество мип уровней для символа (как правило, этот параметр равен нулю); шестой параметр задает, будет ли шрифт курсивный через булевскую переменную; седьмой – задает используемый набор символов (реализуется через константы, например: ANSI_CHARSET, DEFAULT_CHARSET, SYMBOL_CHARSET, RUSSIAN_CHARSET ); восьмой параметр определяет, как операционная система будет выравнивать (подгонять) требуемый размер шрифта с реальным (как правило, используют константу OUT_DEFAULT_PRECIS ); девятый параметр имеет смысл для растровых шрифтов и задает качество интерполяции (по умолчанию используют константу DEFAULT_QUALITY ); десятый параметр определяет расстояние между символами в строке (используют константу DEFAULT_PITCH ); одиннадцатый параметр определяет название шрифта, например Arial, Times New Roman, Courier New; и двенадцатый параметрпеременная (указатель), в которую будет возвращен результат вызова. Ниже приведен пример создания полужирного шрифта высотой 72 пикселей класса Times New Roman.

C++
D3DXCreateFont(device, 72, 0, FW_BOLD, 0, FALSE, DEFAULT_CHARSET, 
            OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,  
            DEFAULT_PITCH, TEXT("Times New Roman"), &font);
Pascal
D3DXCreateFont(device, 72,0, FW_BOLD, 0, false, DEFAULT_CHARSET, 
            OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 
            DEFAULT_PITCH , 'Times New Roman', font);

Следующий шаг – это непосредственный вывод текста на экран. Реализуется он через вызов метода DrawText() интерфейса ID3DXFont. Метод имеет шесть параметров: первый параметр представляет собой указатель на объект ID3DXSprite (значение NULL означает, что библиотека Direct3D будет самостоятельно использовать механизм спрайтов для вывода текста); второй параметр – строка вывода; третий параметр определяет количество символов в строке (значение -1 означает, что библиотека сама подсчитает длину строки); четвертый параметр задает прямоугольную область вывода текста; пятый параметр представляет собой набор флагов, с помощью которых можно разместить выводимый текст в нужных местах (слева, справа, сверху и т.д.); шестой параметр задает цвет, которым будет выведен текст. Ниже приведен пример вывода текста, который выравнивается по правой стороне прямоугольника размерами 400х300 пикселей.

C++
RECT r;
r.left=0;
r.top=10;
r.right=400;
r.bottom=300;
… 
font->DrawText(NULL, "Тверь", -1, &r, DT_RIGHT, 
  D3DCOLOR_XRGB(255,0,0));
Pascal
var
   r: TRect;
…
r:=Rect(0,0,400,300);
font.DrawTextA(nil, 'Тверь', -1, @r, DT_RIGHT, 
  D3DCOLOR_XRGB(255,0,0));

Ниже приведен пример вывода текста на поверхность, покрытую текстурой.


Вывод сцены в текстуру

До сих пор мы производили отображение (вывод) всей сцены непосредственно на форму. Вообще многие графические библиотеки, в том числе и Direct3D, позволяет перенаправить весь вывод не на экран, а в текстуру. С одной стороны этот механизм является довольно простым и понятным, а с другой – очень мощным, позволяющим создавать различные эффекты, среди которых построение зеркальных поверхностей и теней. Вывод в текстуру представляет собой некое расширение вывода на поверхность. Вначале мы должны объявить в программе два объекта – саму текстура и связанную с ней поверхность вывода. Это реализуется следующим образом:

C++
LPDIRECT3DTEXTURE9 RenderTexture = NULL;
LPDIRECT3DSURFACE9 RenderSurface = NULL;
Pascal
var
  RenderTexture: IDirect3DTexture9;
  RenderSurface: IDirect3DSurface9;

Следующий шаг заключается в создании текстуры. Это можно проделать, воспользовавшись, к примеру, функцией D3DXCreateTexture(). Первый аргумент функции это ссылка на устройство вывода; второй и третий параметры задают ширину и высоту создаваемой текстуры соответственно; четвертый аргумент определяет количество мип- уровней (в нашем случае мип-уровни не используются, поэтому передаем ноль); пятый параметр – флаги использования (в нашем случае необходимо передать константу D3DUSAGE_RENDERTARGET, указывающую на то, что текстура будет использоваться как поверхность вывода); шестой аргумент задает пиксельный формат текстуры (здесь, как правило, наиболее часто используются константы D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_R5G6B5 и др.); седьмой параметр – это флаг месторасположения (хранения) текстуры (здесь передаем значение по умолчанию); и последний восьмой аргумент функции – это имя переменной, в которую будет возвращен результат. Ниже приводится пример создания текстуры размером 512х512 пикселей.

C++
D3DXCreateTexture(device, 512, 512, 0, D3DUSAGE_RENDERTARGET, 
           D3DFMT_R8G8B8, D3DPOOL_DEFAULT, &RenderTexture);
Pascal
D3DXCreateTexture(device, 512, 512, 0, D3DUSAGE_RENDERTARGET, 
           D3DFMT_R8G8B8, D3DPOOL_DEFAULT, RenderTexture);

Всевозможные операции с текстурой библиотека Direct3D производит через поверхности. Для того, чтобы получить базовую поверхность любой текстуры, нужно вызвать метод GetSurfaceLevel() интерфейса IDirect3DTexture9. Метод имеет два параметра: первый – это номер текстурного уровня (так как у нас уровень всего один, то передаем ноль), а второй – указатель переменную, в которой будет храниться поверхность.

C++ RenderTexture->GetSurfaceLevel(0, &RenderSurface);
Pascal RenderTexture.GetSurfaceLevel(0, RenderSurface);

И последний шаг в данной методике – это указание поверхности вывода. Этот шаг реализуется через вызов метода SetRenderTarget() интерфейса IDirect3DDevice9. Этот метод имеет два параметра: первый – это индекс поверхности вывода (так как у нас поверхность одна, то передаем нулевое значение); второй аргумент – поверхность вывода.

C++ device->SetRenderTarget(0, RenderSurface);
Pascal device.SetRenderTarget(0, RenderSurface);

Как правило, подобный вызов производится непосредственно в процедуре вывода примитивов перед вызовом метода Clear(). Вывод на поверхность сопряженную с текстурой ничем не отличается от обычного способа. Единственное отличие заключается в том, что результат (вся сцена) будет "воспроизводиться" в текстуре. Для того, чтобы восстановить вывод сцены обратно в буфер отображения ( back buffer ), нужно вначале программы сохранить указатель на этот буфер в некоторую переменную.

C++
LPDIRECT3DSURFACE9 BackBuffer = NULL;
…
device->GetRenderTarget(0, &BackBuffer);
Pascal
var
   BackBuffer: IDirect3DSurface9;
…
device.GetRenderTarget(0, BackBuffer);

Затем необходимо вызвать метод SetRenderTarget(), и в качестве второго параметра передать ссылку на сохраненную поверхность вывода ( back buffer ).

C++ device->SetRenderTarget(0, BackBuffer);
Pascal device.SetRenderTarget(0, BackBuffer);

Поверхность вывода, ассоциированную с текстурой можно в любой момент сохранить в файл на диске. Для этого можно воспользоваться функцией D3DXSaveTextureToFile(), которая имеет четыре параметра. Первый аргумент – это указатель на строку, содержащую имя сохраняемого файла; второй параметр определяет формат графического файла (задается одной из следующих констант: D3DXIFF_BMP, D3DXIFF_JPG, D3DXIFF_TGA, D3DXIFF_PNG, D3DXIFF_DDS, D3DXIFF_PPM, D3DXIFF_DIB, D3DXIFF_HDR, D3DXIFF_PFM ); третий аргумент – это ссылка на интерфейс IDirect3DBaseTexture9, содержащий нужную текстуру; и четвертый параметр представляет собой ссылку на структуру, определяющую палитру из 256 цветов. Ниже приведен пример сохранения поверхности вывода, ассоциированной с текстурой в файл на диске.

C++ D3DXSaveTextureToFile("scene.bmp", D3DXIFF_BMP, RenderTexture, NULL);
Pascal D3DXSaveTextureToFile('scene.bmp', D3DXIFF_BMP, RenderTexture, nil);
< Лекция 4 || Лекция 5: 123 || Лекция 6 >
Artem Alekseyenko
Artem Alekseyenko
Россия, ЯНАО
Андрей Скурихин
Андрей Скурихин
Россия, Санкт-Петербург, Санкт-Петербургский государственный электротехнический университет (ЛЭТИ), 1997