Построение отрезков. Спрайты и вывод текста и сцен в текстуру
Вывод текста
Довольно часто возникает необходимость вывести на экран некоторый текст. Традиционно разработчики двумерных и трехмерных приложений для вывода информационных сообщений использовали следующий подход:
- Создание текстуры, содержащей все буквы алфавита и цифры;
- Определение для каждого символа в текстуре его положения, например, текстурные координаты;
- Когда было нужно выводить текст, создается прямоугольник, содержащий нужный символ;
- Устанавливаются нужные текстурные координаты, и производится вывод;
- Эти шаги повторяются для каждого выводимого символа.
Библиотека Direct3D предоставляет более простые возможности по отображению текста на экране. Как обычно, вначале мы должны объявить переменные интерфейсного типа.
Следующий шаг – это создание самого шрифта с помощью функции 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. Этот метод имеет два параметра: первый – это индекс поверхности вывода (так как у нас поверхность одна, то передаем нулевое значение); второй аргумент – поверхность вывода.
Как правило, подобный вызов производится непосредственно в процедуре вывода примитивов перед вызовом метода Clear(). Вывод на поверхность сопряженную с текстурой ничем не отличается от обычного способа. Единственное отличие заключается в том, что результат (вся сцена) будет "воспроизводиться" в текстуре. Для того, чтобы восстановить вывод сцены обратно в буфер отображения ( back buffer ), нужно вначале программы сохранить указатель на этот буфер в некоторую переменную.
C++ |
LPDIRECT3DSURFACE9 BackBuffer = NULL; … device->GetRenderTarget(0, &BackBuffer); |
Pascal |
var BackBuffer: IDirect3DSurface9; … device.GetRenderTarget(0, BackBuffer); |
Затем необходимо вызвать метод SetRenderTarget(), и в качестве второго параметра передать ссылку на сохраненную поверхность вывода ( back buffer ).
Поверхность вывода, ассоциированную с текстурой можно в любой момент сохранить в файл на диске. Для этого можно воспользоваться функцией D3DXSaveTextureToFile(), которая имеет четыре параметра. Первый аргумент – это указатель на строку, содержащую имя сохраняемого файла; второй параметр определяет формат графического файла (задается одной из следующих констант: D3DXIFF_BMP, D3DXIFF_JPG, D3DXIFF_TGA, D3DXIFF_PNG, D3DXIFF_DDS, D3DXIFF_PPM, D3DXIFF_DIB, D3DXIFF_HDR, D3DXIFF_PFM ); третий аргумент – это ссылка на интерфейс IDirect3DBaseTexture9, содержащий нужную текстуру; и четвертый параметр представляет собой ссылку на структуру, определяющую палитру из 256 цветов. Ниже приведен пример сохранения поверхности вывода, ассоциированной с текстурой в файл на диске.