Уроки OpenGL + C#.

Текстурирование в OpenGL (с помощью библиотеки DevIL).

 

 

Разработка программы начинается с создания оболочки.

Создайте окно программы и разместите на ней элемент openglsimplecontrol , как показано на рисунке 1, после чего установите его размеры 500х500. Переименуйте данный объект, дав ему имя AnT.

Окно создаваемой программы.
Рисунок 1.


Так же не забудьте установить ссылки на используемые библиотеки Tao (рисунок 2). Обратите внимание на ссылку на Tao.DevIL - данная библиотека необходима нам для загрузки текстур ( и не забудьте using Tao.DevIl; иначе вы так же не сможете работать с данной бибилиотекой) .

Подключение библиотек Tao.
Рисунок 2.

 

Для реализации визуализации будет использоваться таймер – после инициализации окна он будет генерировать событие, называемое тиком таймера, раз в 30 миллисекунд – добавьте элемент таймер, переименуйте экземпляр в RenderTimer и установите время тика 30 миллисекунд (как показано на рисунке 3), а так же добавьте ему событие для обработки тика.

Настройка таймера.
Рисунок 3.

Так же необходимо добавить меню, для выбора файлов. Для этого добавьте новое меню на форму, объект openFileDialog. В свойствах объекта openFileDialog установите параметр Filter равным «JPG files|*.jpg|All files|*.*».

Создание меню.
Рисунок 4.

 

Инициализация OpenGl происходит как обычно, следует отметить только дополнительную инициализация бибилиотеки openIL. Нам потребуется объявить ряд переменных, для дальнейшей работы программы:


// событие загрузки формы
private void Form1_Load( object sender, EventArgs e)
{
// инициализация бибилиотеки glut
Glut.glutInit();
// инициализация режима экрана
Glut.glutInitDisplayMode( Glut.GLUT_RGB | Glut.GLUT_DOUBLE);

// инициализация библиотеки openIL
Il.ilInit();
Il.ilEnable( Il.IL_ORIGIN_SET);

// установка цвета очистки экрана (RGBA)
Gl.glClearColor(255, 255, 255, 1);

// установка порта вывода
Gl.glViewport(0, 0, AnT.Width, AnT.Height);

// активация проекционной матрицы
Gl.glMatrixMode( Gl.GL_PROJECTION);
// очистка матрицы
Gl.glLoadIdentity();

// установка перспективы
Glu.gluPerspective(30, AnT.Width / AnT.Height, 1, 100);

// установка объектно-видовой матрицы
Gl.glMatrixMode( Gl.GL_MODELVIEW);
Gl.glLoadIdentity();

// начальные настройки OpenGL
Gl.glEnable( Gl.GL_DEPTH_TEST);
Gl.glEnable( Gl.GL_LIGHTING);
Gl.glEnable( Gl.GL_LIGHT0);

// активация таймера
RenderTimer.Start();
}


Теперь рассмотрим процесс загрузки текстуры и создания файла. Для этого мы реализуем 2 функции – первая выполняется как обработка события активации меню, размещенного на нашей форме. Получив имя текстуры мы проведем начальную подготовку к загрузке текстуры в память графического адаптера.

В дальнейшем мы выполним дополнительные настройки текстуры, после которых сразу же увидим результат.


// обработка пункта меню загрузки изображения
private void loadImageToolStripMenuItem_Click( object sender, EventArgs e)
{
// открываем окно выбора файла
DialogResult res = openFileDialog1.ShowDialog(); // есл файл выбран - и возвращен результат OK
if (res == DialogResult.OK)
{
// создаем изображение с индификатором imageId
Il.ilGenImages(1, out imageId);
// делаем изображение текущим
Il.ilBindImage(imageId);

// адрес изображения полученный с помощью окна выбра файла
string url = openFileDialog1.FileName;

// пробуем загрузить изображение
if ( Il.ilLoadImage(url))
{

// если загрузка прошла успешно
// сохраняем размеры изображения
int width = Il.ilGetInteger( Il.IL_IMAGE_WIDTH);
int height = Il.ilGetInteger( Il.IL_IMAGE_HEIGHT);

// определяем число бит на пиксель
int bitspp = Il.ilGetInteger( Il.IL_IMAGE_BITS_PER_PIXEL);

switch (bitspp) // в зависимости оп полученного результата
{

// создаем текстуру используя режим GL_RGB или GL_RGBA
case 24:
mGlTextureObject = MakeGlTexture( Gl.GL_RGB, Il.ilGetData(), width, height);
break ;
case 32:
mGlTextureObject = MakeGlTexture( Gl.GL_RGBA, Il.ilGetData(), width, height);
break ;

}

// активируем флаг, сигнализирующий загрузку текстуры
textureIsLoad = true ;
// очищаем память
Il.ilDeleteImages(1, ref imageId);

}
}
}

// создание текстуры в панями openGL
private static uint MakeGlTexture( int Format, IntPtr pixels, int w, int h)
{
// индетефекатор текстурного объекта
uint texObject;

// генерируем текстурный объект
Gl.glGenTextures(1, out texObject);

// устанавливаем режим упаковки пикселей
Gl.glPixelStorei( Gl.GL_UNPACK_ALIGNMENT, 1);

// создаем привязку к только что созданной текстуре
Gl.glBindTexture( Gl.GL_TEXTURE_2D, texObject);

// устанавливаем режим фильтрации и повторения текстуры
Gl.glTexParameteri( Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_S, Gl.GL_REPEAT);
Gl.glTexParameteri( Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_WRAP_T, Gl.GL_REPEAT);
Gl.glTexParameteri( Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
Gl.glTexParameteri( Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
Gl.glTexEnvf( Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_MODE, Gl.GL_REPLACE);

// создаем RGB или RGBA текстуру
switch (Format)
{

case Gl.GL_RGB:
Gl.glTexImage2D( Gl.GL_TEXTURE_2D, 0, Gl.GL_RGB, w, h, 0, Gl.GL_RGB, Gl.GL_UNSIGNED_BYTE, pixels);
break ;

case Gl.GL_RGBA:
Gl.glTexImage2D( Gl.GL_TEXTURE_2D, 0, Gl.GL_RGBA, w, h, 0, Gl.GL_RGBA, Gl.GL_UNSIGNED_BYTE, pixels);
break ;

}

// возвращаем индетефекатор текстурного объекта

return texObject;
}


Теперь остается обработать событие отклика таймера и реализовать функцию визуализации сцены. При визуализации текстуры нам необходимо включить режим текстурирования, а так же при выводе вершин объектов, привязывать к ним текстурные координаты, в соотвествии с которыми произойдет наложение текстуры.


// отклик таймера
private void RenderTimer_Tick( object sender, EventArgs e)
{
// вызов функции отрисовки сцены
Draw();
} // функция отрисовки
private void Draw()
{
// если текстура загружена
if (textureIsLoad)
{

// увеличиваем угол поворота
rot++;
// корректируем угол
if (rot > 360)
rot = 0;

// очистка буфера цвета и буфера глубины
Gl.glClear( Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
Gl.glClearColor(255, 255, 255, 1);
// очищение текущей матрицы
Gl.glLoadIdentity();

// включаем режим текстурирования
Gl.glEnable( Gl.GL_TEXTURE_2D);
// включаем режим текстурирования , указывая индификатор mGlTextureObject
Gl.glBindTexture( Gl.GL_TEXTURE_2D, mGlTextureObject);

// сохраняем состояние матрицы
Gl.glPushMatrix();

// выполняем перемещение для более наглядного представления сцены
Gl.glTranslated(0, -1, -5);
// реализуем поворот объекта
Gl.glRotated(rot, 0, 1, 0);

// отрисовываем полигон
Gl.glBegin( Gl.GL_QUADS);

// указываем поочередно вершины и текстурные координаты
Gl.glVertex3d(1, 1, 0);
Gl.glTexCoord2f(0, 0);
Gl.glVertex3d(1, 0, 0);
Gl.glTexCoord2f(1, 0);
Gl.glVertex3d(0, 0, 0);
Gl.glTexCoord2f(1, 1);
Gl.glVertex3d(0, 1, 0);
Gl.glTexCoord2f(0, 1);

// завершаем отрисовку
Gl.glEnd();

// возвращаем матрицу
Gl.glPopMatrix();
// отключаем режим текстурирования
Gl.glDisable( Gl.GL_TEXTURE_2D);

// обновлеям элемент со сценой
AnT.Invalidate();

}
}


Результат работы программы

 

- вращающаяся плоскость с изображением текстуры.

Результат работы программы - вращающаяся протекстурированная плоскость.
Рисунок 5.


Исходный код этого урока - текстурирование OpenGL (DevIL)

 

Обсуждение данного урока: Текстурирование в openGl - библиотека DevIL  (OpenIL).
Далее: 13.1 Теоретическое введение - представление 3D объектов, формат ASE. Экспорт 3D модели в формат ASE из 3D studio Max.