OpenGL в Delphi

       

Если в кадре используется




Начинающие часто спрашивают, как организовать работу с несколькими текстурами. Этот пример показывает два возможных способа эффективной организации такой работы.
Первый способ состоит в использовании дисплейных списков, здесь они оказываются как нигде кстати. На этом простом примере эффективность такого подхода пока мало заметна, но нас ждет еще один пример, где она проявится в полной мере.
Дисплейные списки при компиляции запоминают только команды OpenGL, поэтому при вызове списка все промежуточные действия по подготовке образа текстуры не будут затормаживать работу приложения Использование списков существенно облегчает работу также с точки зрения кодирования: нет необходимости держать массивы под каждый образ и переключаться между ними по ходу работы приложения.
В примере описываются два списка, каждый из которых содержит код по подготовке образов. Перед тем как нарисовать примитив, вызывается нужный список. Сами массивы образов могут уже использоваться для других нужд или вовсе не существовать (не существуют они и для нашей программы, а образы текстуры хранятся в памяти, занятой OpenGL).
Этот пример иллюстрирует и другой способ, основанный на использовании недокументированных команд.
Команда glBmdTexture позволяет связывать текстуры, создавать и вызывать именованные последовательности команд подобные дисплейным спискам, но предназначенные для идентификации только текстур. С ней связаны команда glGenTextures, генерирующая имена текстур, и команда glDeleteTextures, освобождающая память от текстурных списков

Замечание
Прототипы всех этих команд необходимо задавать самостоятельно

По выбору можно использовать любой из этих двух способов, выбор управляется переменной HaveTexObj.
В программе массив техОbj, состоящий из двух целых, хранит имена дисплейных или текстурных списков. Значения идентификаторов генерируются системой OpenGL:

if HaveTexObj // используются текстурные списки
then glGenTextures( 2, @TexObj) // генерировать два имени
else begin // используются дисплейные списки
TexObj[0] := glGenLists(2); // генерировать имена дисплейных
// списков
TexObj[1] := ТехОЬj[0]+1;
end;

При подготовке текстуры создается одна из двух разновидностей списков, для команды glBmdTexture концом описания списка является начало описания следующего:

if HaveTexObj // использовать текстурные списки
then glBmdTexture ( GL_TEXTURE_2D, TexObj [0]) // описание
else glNewList( TexObjf[0], GL_COMPILE); // начало для дисплейного
// списка
// красным на белом
For i:=0 to height-1 do
For j:=0 to width - 1 do begin p := i*width+];
if (texl[ (height-i-1) *width+;j]) <>0 then begin
tex[p] [0] := 255;
tex[p][1] := 0;
tex[p] [2] := 0;
end
else begin
tex[p][0] := 255;
tex[p][1] := 255;
tex[p][2] := 255;
end
end;
// собственно создание текстуры
glTexImage2D( GL_TEXTURE_2D, 0, 3, width, height, 0,
GL_RGB, GLJJNSIGNED_BYTE, @tex);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
If not HaveTexObj then glEndList;

Перед рисованием примитивов вызывается нужный список:

glPushMatrix;
glTranslatef( -1.0, 0.0, 0.0);
glRotatef( Angle, 0.0, 0.0, 1.0);
if HaveTexObj // какой из типов списков вызывать
then glBmdTexture ( GL_TEXTURE_2D, ТехОbj[0])
else glCallList( ТехОbj[0]);//здесь хранятся только параметры
glBegin( GL_POLYGON) ;
glTexCoord2f( 0.0, 0.0);
glVertex2f( -1.0, -1.0);
glTexCoord2f( 1.0, 0.0);
glVertex2f( 1.0, -1.0);
glTexCoord2f( 1.0, 1.0);
glVertex2f( 1.0, 1.0);
glTexCoord2f( 0.0, 1.0);
glVertex2f( -1.0, 1.0);
glEnd;
glPopMatrix;

В конце работы, как это принято в среде культурных программистов, память освобождается:

if HaveTexObj
then glDeleteTextures( 2, STexObj) // для текстурных списков
else glDeleteLists (TexObj[0], 2);

Возможно, вы захотите использовать для своих проектов традиционную для Демонстрационных программ текстуру в виде кирпичной кладки, тогда можете взять в качестве шаблона проект из подкаталога Ех85, где найдете все необходимые "стройматериалы"
(Рисунок 4 58).



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