Цель лекции: Рассмотреть создание текстуры из файла формата BMP, реализацию команд инициализации текстуры, изменения свойств текстуры и определения координат текстуры на Object Pascal и на C# с использованием библиотеки OpenTK.
Пример № 9.1 Пример демонстрирует наложение нескольких копий текстуры на квадрат.
Пример № 9.2 Пример демонстрирует наложение текстуры на поверхность сферы.
Пример № 9.3 Пример демонстрирует формирование изображения цилиндра с наложением текстуры на его поверхность.
Под текстурой обычно понимают растровое изображение, отображаемое на гранях примитивов.
Предварительно содержание текстуры должно быть передано в библиотеку OpenGL. Для этого передается указатель на массив с информацией о текстуре. Информация о текстуре представляет собой построчное представление изображения в формате:
RGB….RGB RGB….RGB RGB….RGB
Где RGB – это красная, зеленая и синяя составляющие цвета каждого пиксела текстуры.
Размер текстуры должен быть кратен степени двойки: 32x32, 32x64, 128x256 и т д. Текстура может быть подготовлена различным образом: может быть сформирована программно или, например, загружена из какого-либо файла.
Одним из наиболее близких форматов к формату текстуры OpenGL является формат хранения графических изображений BMP. Отличие в хранении данных о пикселах между форматом BMP и форматом текстуры OpenGL заключается в различном порядке байт, описывающих составляющие цвета пиксела. В формате BMP данные о каждом пикселе хранятся в порядке: BGR. В формате текстуры OpenGL цветовые характеристики пикселов хранятся в противоположном порядке: RGB.
Формат файла BMP кроме самого изображения содержит так же общую информацию о нем. Например, такую как, формат изображения (в файле формата BMP изображение может храниться в нескольких разных вариантах), ширину и высоту изображения и др.
В программе на C# для использования изображения в формате ).
public static void LoadTexture(Bitmap bmp)
{
BitmapData data = bmp.LockBits(
new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
GL.TexImage2D(TextureTarget.Texture2D, 0,
PixelInternalFormat.Rgb, data.Width, data.Height, 0,
OpenTK.Graphics.OpenGL.PixelFormat.Bgr,
PixelType.UnsignedByte, data.Scan0);
bmp.UnlockBits(data);
}
В качестве параметра методу передается объект типа ):
Bitmap bmpTex;
bmpTex = new Bitmap("OGL64x64.bmp");
В методе LoadTexture сначала вызывается метод LockBits объекта Bitmap, который блокирует объект в системной памяти. Затем вызывается метод GL.TexImage2D, который передает изображение в библиотеку OpenGL в качестве текстуры. В конце метода LoadTexture вызывается метод UnlockBits объекта Bitmap, который разблокирует объект в памяти.
В Object Pascal для использования изображения в формате BMP выполняются аналогичные действия. В листинге 9.3 приведена процедура, выполняющая загрузку изображения из файла формата BMP и его преобразование в формат текстуры OpenGL на языке Object Pascal. Для хранения информации о текстуре используется структура TGLTexture, в котором изображение текстуры хранится в динамическом массиве. Поля Height и Width структуры хранят информацию о высоте и ширине изображения в пикселах. Информация о размере текстуры необходима для инициализации текстуры.
type
TGLTexture = record
Height: Integer;
Width: Integer;
Data: array of Byte;
end;
procedure LoadTextureFromBMP(const AFileName: String; var ATexture: TGLTexture);
var
i, j: Integer;
bmp: TBitmap;
begin
bmp := TBitmap.Create;
try
bmp.LoadFromFile(AFileName); // загрузка текстуры из файла
ATexture.Height := bmp.Height;
ATexture.Width := bmp.Width;
SetLength(ATexture.Data, bmp.Width* bmp.Height*3);
// заполнение битового массива
For i:=0 to bmp.Height-1 do
For j:=0 to bmp.Width-1 do begin
ATexture.Data[(i*bmp.Width+j)*3+0]:=
GetRValue(bmp.Canvas.Pixels[j, i]);
ATexture.Data[(i*bmp.Width+j)*3+1]:=
GetGValue(bmp.Canvas.Pixels[j, i]);
ATexture.Data[(i*bmp.Width+j)*3+2]:=
GetBValue(bmp.Canvas.Pixels[j, i]);
end;
finally
bmp.Free;
end;
end;
При формировании изображения используется текущая текстура. Для определения текущей текстуры и её параметров используется команда TexImage2D:
C#: void TexImage2D(TextureTarget target, int level, PixelInternalFormat internalformat, int width, int height, int border, PixelFormat format, PixelType type, IntPtr pixels); Object Pascal: procedure glTexImage2D (target: GLenum; level, components: GLint; width, height: GLsizei; border: GLint; format, _type: GLenum; pixels: Pointer);
Параметры команды:
target – определяет тип текстуры, параметр должен быть равен значению TextureTarget.Texture2D при использовании библиотеки OpenTK на C# и значению GL_TEXTURE_2D на Object Pascal.level – уровень детализации текстуры, значение должно быть равно 0.components – определяет количество цветовых компонентов в данных о текстуре. В C# значения этого параметра определяются перечислением PixelInternalFormat.
В Object Pascal параметр может принимать значения 1,2,3,4 и ряд специальных констант. При использовании команды в листингах 9.2 и 9.3 значение этого параметра равно 3, так как в файле формата BMP для каждого пиксела в массиве хранится три цветовых компонента.
width – ширина текстуры в пикселах.height – высота текстуры в пикселах.border – размер "окантовки", значение должно быть равно 0.format - формат передаваемых данных о текстуре.PixelFormat. В Object Pascal параметр может принимать ряд значений, например, GL_RGB, GL_RGBA. _type – определяет тип данных, используемый для передачи каждой составляющей цвета. В формате BMP для каждой составляющей цвета используется беззнаковое байтовое значение. Поэтому в C# для этого используется значение PixelType.UnsignedByte, а в Object Pascal –значение GL_UNSIGNED_BYTE.pixels - указатель на блок памяти с подготовленным изображением текстуры в формате OpenGL. В Object Pascal при использовании процедуры из листинга 9.3 это должен быть указатель на нулевой элемент динамического массива поля Data структуры TGLTexture.Для настройки параметров отображения текстуры, которые используются при изменении её положения в пространстве и масштабировании, используется команда TexParameter. Как и для многих других команд она реализуется в C# набором статических методов класса GL с различными типами параметров, а в Object Pascal – набором процедур с различным постфиксом и соотвествующими типами параметров. Ниже приведен вариант её реализация в C# и в Object Pascal для варианта, когда в качестве параметра передаётся целочисленное значение.
C#: void TexParameter(TextureTarget target, TextureParameterName pname, int param); Object Pascal: procedure glTexParameteri (target, pname: GLenum; param: GLint);
Параметры процедуры:
target – тип текстуры для которой определяются параметры. На C# параметр должен быть равен значению Texture2D перечисления TextureTarget, в Object Pascal – значению GL_TEXTURE_2D.| Описание | OpenTK, C# | Object Pascal |
|---|---|---|
| Функция увеличения текстуры при масштабировании | TextureParameterName. TextureMagFilter | GL_TEXTURE_MAG_FILTER |
| Функция уменьшения текстуры при масштабировании | TextureParameterName. TextureMinFilter | GL_TEXTURE_MIN_FILTER |
| Описание | OpenTK, C# | Object Pascal |
|---|---|---|
| В качестве значения берется точка текстуры с ближайшими координатами | TextureMinFilter.Nearest | GL_NEAREST |
| В качестве значения берется среднеарифметическое значение на основе 4 точек рядом с координатами точки | TextureMinFilter.Linear | GL_LINEAR |
В листинге 9.4 приведен пример загрузки и инициализации текстуры на C# с помощью метода LoadTexture из листинга 9.1 .
Bitmap bmpTex;
private void Form1_Load(object sender, EventArgs e)
{
bmpTex = new Bitmap("OGL64x64.bmp");
GLTexture.LoadTexture(bmpTex);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.Enable(EnableCap.Texture2D);
}
В листинге 9.5 приведен пример загрузки и инициализации текстуры на Object Pascal с помощью процедуры LoadTextureFromBMP из листинга 9.3 .
Var
Tex1: TGLTexture;
…
procedure TfrmGL.FormCreate(Sender: TObject);
begin
…
LoadTextureFromBMP('..\OGL64x64.bmp', Tex1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Tex1.Width, Tex1.Height,
0, GL_RGB, GL_UNSIGNED_BYTE, @Tex1.Data[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glEnable(GL_TEXTURE_2D);
…
end;
Для отображения текстуры, кроме загрузки текстуры и её инициализации, так же необходимо включить режим отображения текстуры с помощью команды Enable. Поэтому в листингах 9.4 и 9.5 после загрузки и инициализации текстуры вызывается команда Enable с параметром EnableCap.Texture2D на C# и параметром GL_TEXTURE_2D на Object Pascal для включения режима отображения текстуры. Для отключения режима отображения текстуры используется команда Disable.
При формировании сложной сцены может потребоваться, чтобы одни объекты отображались с текстурой, а другие – без неё. В этом случае необходимо перед формированием одних объектов включать режим отображения текстуры, а перед формированием других объектов отключать формирование текстуры.
Задание координат текстуры позволяет сопоставить вершины примитивов с изображением текстуры. Вне зависимости от размера изображения текстуры в пикселах, координаты текстуры определяются библиотекой OpenGL в интервале значений [0, 1].
Для правильного изображения текстуры координата текстуры, соответствующая вершине, должна определяться с помощью команды TexCoord перед заданием координат соответствующей вершины примитива.
В библиотеке OpenTK (C#) команда реализуется с помощью набора статических методов класса GL с различними типами параметров, в Object Pascal – с помощью набора процедур. Ниже приведен вариант для случая, когда координаты указываются в качестве значений типа float:
C#: void TexCoord2(float s, float t); Object Pascal: procedure glTexCoord2f (s,t: GLfloat);
Параметры:
s – горизонтальная координата текстуры;t – вертикальная координата текстуры.Ниже приведен пример наложения текстуры на квадрат (рис 9.1).
GL.Begin(BeginMode.Quads); GL.TexCoord2(0.0f, 0f); GL.Vertex2(-0.5f, -0.5f); GL.TexCoord2(0.0f, 1f); GL.Vertex2(-0.5f, 0.5f); GL.TexCoord2(1f, 1f); GL.Vertex3(0.5f, 0.5f); GL.TexCoord2(1f, 0f); GL.Vertex3(0.5f, -0.5f); GL.End(); | glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex2f(-0.5, -0.5); glTexCoord2f(0,1); glVertex2f(-0.5, 0.5); glTexCoord2f(1,1); glVertex2f(0.5, 0.5); glTexCoord2f(1,0); glVertex2f(0.5, -0.5); glEnd; |
(рис 9.1) Результат наложения текстуры на квадрат
Если необходимо, чтобы изображение дублировалось при наложении на примитив по горизонтали и/или вертикали, то в этом случае при задании координат текстуры необходимо указать значение больше 1. В листингах 9.8 и 9.9 приведен пример наложения текстуры, в котором изображение повторяется 4 раза по вертикали и по горизонтали (рис 9.8" type="example">листингах 9.8 и 9.9 приведен пример наложения текстуры, в котором изображение повторяется 4 раза по вертикали и по горизонтали (int w = 4;
int h = 4;
…
GL.Begin(BeginMode.Quads);
GL.TexCoord2(0.0, w); GL.Vertex3(-1.0f, 1.0f, 0.0f);
GL.TexCoord2(0.0, 0.0); GL.Vertex3(-1.0f, -1.0f, 0.0f);
GL.TexCoord2(h, 0.0); GL.Vertex3(1.0f, -1.0f, 0.0f);
GL.TexCoord2(h, w); GL.Vertex3( 1.0f, 1.0f, 0.0f);
GL.End();
При необходимости наложения текстуры на сложный объект координаты текстуры определяются индивидуально для каждого примитива. Ниже приведен пример наложения текстуры на сферу. Текстура как бы разбивается на прямоугольники, и каждый прямоугольник накладывается на отдельный четырехугольный примитив, из которых формируется поверхность сферы. Методу класса В На практике часто используются двухмерные (поверхностные) тектуры. Этот тип текстур имеет две координаты Привязка текстуры к вершинам примитива выполняется с помощью команды var
w,h: Integer;
begin
…
w := 4; h := 4;
glEnable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glTexCoord2f(0.0, w); glVertex3f(-1.0, 1.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(h, 0.0); glVertex3f( 1.0, -1.0, 0.0);
glTexCoord2f(h, w); glVertex3f( 1.0, 1.0, 0.0);
glEnd;
glDisable(GL_TEXTURE_2D);
…
end;
(рис 9.2) Пример дублирования текстуры
Наложение текстуры на сложные объекты
void sphere(double r, int nx, int ny)
{
int i, ix, iy;
double x, y, z;
for (iy=0; iy < ny; ++iy)
{
GL.Begin(BeginMode.QuadStrip);
for (ix = 0; ix <= nx; ++ix)
{
x = r * Math.Sin(iy * Math.PI / ny) * Math.Cos(2 * ix * Math.PI / nx);
y = r * Math.Sin(iy * Math.PI / ny) * Math.Sin(2 * ix * Math.PI / nx);
z = r * Math.Cos(iy * Math.PI / ny);
//нормаль направлена от центра
GL.Normal3(x, y, z);
GL.TexCoord2((double)ix / (double)nx, (double)iy / (double)ny);
GL.Vertex3(x, y, z);
x = r * Math.Sin((iy + 1) * Math.PI / ny) *
Math.Cos(2 * ix * Math.PI / nx);
y = r * Math.Sin((iy + 1) * Math.PI / ny) *
Math.Sin(2 * ix * Math.PI / nx);
z = r * Math.Cos((iy + 1) * Math.PI / ny);
GL.Normal3(x, y, z);
GL.TexCoord2((double)ix / (double)nx, (double)(iy + 1) / (double)ny);
GL.Vertex3(x, y, z);
}
GL.End();
}
}
procedure sphere(r: GLFloat; nx, ny: integer);
var
i, ix, iy: integer;
x, y, z: GLFloat;
begin
for iy:=0 to ny-1 do begin
glBegin(GL_QUAD_STRIP);
for ix:=0 to nx do begin
x:= r*sin (iy*pi/ny)*cos(2*ix*pi/nx);
y:=r * sin (iy*pi/ny)*sin(2*ix*pi/nx);
z:= r* cos(iy*pi/ny);
glNormal3f(x, y, z);
glTexCoord2f(ix/nx, iy/ny);
glVertex3f(x, y, z);
x:= r*sin ((iy+1)*pi/ny)*cos(2*ix*pi/nx);
y:=r * sin ((iy+1)*pi/ny)*sin(2*ix*pi/nx);
z:= r* cos((iy+1)*pi/ny);
glNormal3f(x, y, z);
glTexCoord2f(ix/nx, (iy+1)/ny);
glVertex3f(x, y, z);
end;
glEnd;
end;
end;
sphere на C# и процедуре sphere на Object Pascal передаются три параметра:
r – радиус сферы;nx и ny – количество окружностей параллельных плоскостям YX и XZ, которые используются для формирования изображения поверхности сферы.
(рис 9.3) Пример наложения текстуры на сферу
Краткие итоги
OpenGL реализована поддержка нескольких типов текстур: линейных, поверхностных (двухмерных) и объемных (трехмерных) текстур.s и t. Изображение для текстуры может быть сформировано программно или загружено из графического файла, например, формата BMP.TexCoord2. Для инициализации текстуры используется команда TexImage2D. Для отображения тектуры должны быть так же заданы алгоритмы масштабирования текстуры с помощью команды TexParameter. Отображение тектуры может быть включено и выключено при формировании примитивов с помощью команд Enable и Disable.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.