OpenGL в Delphi

       

Выводить символы в OpenGL совсем несложно




Замечание
Обратите внимание, что при описании формата пикселов я явно задаю значение поля cDepthBits, иначе буквы покрываются ненужными точками.

При начале работы приложения вызывается команда, подготавливающая списки для каждого символа текущего шрифта формы:

wgiuseFontOutimes (Canvas.Handle, 0, 255, GLF_START_LIST, 0.0, 0.15,
WGL_FONT_POLYGONS, nil);

Замечание
В этом примере для получения контекста воспроизведения обязательно нужно использовать самостоятельно полученную ссылку на контекст устройства Если вместо DC использовать Canvas.Handle, вывод может получиться неустойчивым: при одном запуске приложения окно черное, а при следующем - все в порядке.

Цвет шрифта, установленного в окне, при выводе текста не учитывается, в этом отношении выводимые символы ничем не отличаются от прочих геометрических объектов. Свойства материала и источника света необходимо задавать самостоятельно.
Возможно, кому-то из читателей потребуется использовать вывод текста в приложениях, написанных без использования VCL. В примере из подкаталога Ex11 делается то же, что и в предыдущем, но шрифт отличается. Ну и, конечно, вырос размер кода:

var
hFontNew, hOldFont : HFONT;
// подготовка вывода текста FillChardf, SizeOf(lf), 0) ;
If.lfHeight = -28;
If.lfWeight = FW_NORMAL;
If.lfCharSet = ANSI_CHARSET;
If.IfOutPrecision = OUT_DEFAULT_PRECIS;
If.IfClipPrecision = CLIP_DEFAULT_PRECIS;
If.lfQuality = DEFAULT_QUALITY;
If.IfPitchAndFamily = FF_DONTCARE OR DEFAULT_PITCH;
Istrcpy (If.IfFaceName, 'Arial Cyr');
hFontNew := CreateFontlndirect(If);
hOldFont := SelectObject(DC,hFontNew);
wgiUseFontOutlines(DC, 0, 255, GLF_START_LIST, 0.0, 0.15,
WGL_FONT_POLYGONS, nil);
DeleteObject(SelectObject(DC,h01dFont));
DeleteObject(SelectObject(DC,hFontNew));

Рассмотрим команду wgiuseFontOutimes. Первый параметр - ссылка на контекст устройства, в котором должен быть установлен соответствующий шрифт. Второй и третий параметры задают интервал кодов символов, для которых будут строиться списки. Четвертый параметр задает базовое значение для идентификации списков - для каждого символа создается отдельный список, нумеруются они по порядку, начиная с задаваемого числа. Пятый параметр, называемый "отклонение", задает точность воспроизведения символов; чем меньше это число, тем аккуратнее получаются символы, за счет ресурсов, конечно. Шестой параметр, выдавливание, задает глубину получаемых символов в пространстве. Седьмой параметр определяет формат построения, линиями или многоугольниками. Последний, восьмой, параметр - указатель на массив специального типа TGLYPHMETRICSFLOAT или NULL, если эти величины не используются (в Delphi здесь необходимо задавать ml).
Думаю, вы заметили, что операция построения 256 списков сравнительно длительная, после запуска приложения на это тратится несколько секунд.
Для собственно вывода текста я прибегнул к небольшой уловке, написав следующую, хоть и небольшую, но отдельную, процедуру

procedure OutText (Litera : PChar);
begin
glListBase(GLF_START_LIST); // смещение для имен списков
// вызов списка для каждого символа
glCallLists(Length (Litera), GL_UNSIGNED_BYTE, Litera);
end;

Здесь скрыто использование преобразования типа выводимого символа в PChar, и вызов процедуры, например, OutText ('проба'), выглядит привычным образом. Вывод текста состоит из двух действий - команда giListBase задает базовое смещение для вызываемых списков, а команда glCallLists вызывает на выполнение списки, соответствующие выводимому тексту.

Замечание
Смещение имен списков в общем случае использовать не обязательно, обычно это делается для того, чтобы отделить собственные списки программы от вспомогательных списков для символов Второй аргумент команды glCallLists - указатель на список имен дисплейных списков, если аргумент имеет тип PChar, то мы передаем этим аргументом список кодов нужных символов выводимой строки.

Используемые для вывода символов списки должны по окончании работы приложения удаляться точно так же, как и прочие дисплейные списки:

glDeleteLists (GLF_START_LIST, 256);

Как я уже отмечал, подготовка списков для всех 256 символов - процесс сравнительно длительный, и очень желательно сократить время его выполнения. Для этого можно брать не все символы таблицы, а ограничиться только некоторыми пределами. Например, если будут выводиться только заглавные буквы латинского алфавита, третий параметр команды wgiuseFontOutimes достаточно взять равным 91, чтобы захватить действительно используемые символы.
А теперь посмотрим проект из подкаталога Ех12, пример на анимацию: текст крутится в пространстве, меняя цвет - изменяются свойства материала. На символы текста накладывается одномерная текстура

Замечание
В примерах этого раздела на сцене присутствуют только символы текста При их выводе текущие настройки сцены сбиваются Начинающие очень часто, натыкаясь на эту проблему, оказываются всерьез озадаченными Необходимо перед выводом символов запоминать текущие настройки, вызывая команду glPushAttrib с аргументом GL_ALL_ATTRIB_BITS, а после вывода символов вызывать glPopAttrib

Рассмотрим другой режим вывода текста, основанный на использовании команды wgiuseFontBitmaps Такой способ, пожалуй, редко будет вами применяться, поскольку с успехом может быть заменен на использование текстур.
Посмотрите пример из подкаталога Ех13, отличающийся от первого примера на вывод текста только тем, что команда wgiuseFontOutimes заменена на wgiuseFontBitmaps. Символы в этом случае выводятся аналогично обыкновенному выводу Windows, то есть текст выглядит просто как обычная метка. Как сказано в справке по команде wgiuseFontBitmaps, ею удобно пользоваться, когда вывод средствами GDI в контексте воспроизведения невозможен.
Обратите внимание, что, хотя все связанные с пространственными преобразованиями команды присутствуют в тексте программы, вывод выглядит плоским, а перед выводом директивно задается опорная точка для вывода текста:

glRasterPos2f (0,0);

Как следует из документации, для вывода символов, подготовленных командой wgiuseFontBitmaps, неявно вызывается команда glBitmap. Подобный вывод текста предлагается использовать для подрисуночных подписей, что и проиллюстрировано примером из подкаталога Ех14 (рис 6.6).



Содержание раздела