12.2 Текстурирование в openGl - библиотека DevIL (OpenIL).

Необходимые знания:
Вам могут понадобится следующие статьи:

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

Создайте окно программы и разместите на ней элемент openglsimplecontrol, как показано на рисунке 1, после чего установите его размеры 500х500. Переименуйте данный объект, дав ему имя AnT.
Уроки OpenGL + C#: Окно создаваемой программы Рисунок 1. Окно создаваемой программы.
Также не забудьте установить ссылки на используемые библиотеки Tao (рис. 2). Обратите внимание на ссылку на Tao.DevIL - данная библиотека необходима нам для загрузки текстур (и не забудьте using Tao.DevIl; иначе вы не сможете работать с данной библиотекой) .
Уроки OpenGL + C#: Подключение библиотек Tao Рисунок 2. Подключение библиотек Tao.
Для реализации визуализации будет использоваться таймер – после инициализации окна он будет генерировать событие, называемое тиком таймера раз в 30 миллисекунд. Добавьте элемент таймер, переименуйте экземпляр в RenderTimer и установите время тика 30 миллисекунд (как показано на рисунке 3), а также добавьте ему событие для обработки тика.
Уроки OpenGL + C#: Настройка таймера Рисунок 3. Настройка таймера.
Также необходимо добавить меню для выбора файлов. Для этого добавьте новое меню на форму, объект openFileDialog. В свойствах объекта openFileDialog установите параметр Filter равным «JPG files|*.jpg|All files|*.*».
Уроки OpenGL + C#: Создание меню Рисунок 4. Создание меню.
Инициализация OpenGl происходит как обычно, следует отметить только дополнительную инициализация библиотеки openIL. Нам потребуется объявить ряд переменных для дальнейшей работы программы:

/*http://esate.ru, Anvi*/

// ряд вспомогательных переменных
// поворот
private int rot = 0;
// флаг - загружена ли текстура
private bool textureIsLoad = false;

// имя текстуры
public string texture_name = "";
// идентификатор текстуры
public int imageId = 0;

// текстурный объект
public uint mGlTextureObject = 0;

// событие загрузки формы 
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();

}


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

/*http://esate.ru, Anvi*/


// обработка пункта меню загрузки изображения 
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;
}


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

/*http://esate.ru, Anvi*/


// отклик таймера 
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();
  }

}


Результат работы программы - вращающаяся плоскость с изображением текстуры.
Уроки OpenGL + C#: Результат работы программы Рисунок 5. Результат работы программы.

Примечания

В случае возникновения ошибки: Unable to find an entry point named 'ilInit' in DLL 'DevIL.dll'. или подобных:
  • Перейдите: Мой компьютер -> Свойства -> Дополнительные параметры системы -> Переменные среды...
  • В списках системных переменных выберите Path, нажмите «Изменить...»
  • Поставьте в конце    ;    (точку с запятой) и затем добавь путь к TaoFramework\bin, например, C:\Program Files (x86)\TaoFramework\bin;, а также к TaoFramework\lib (путь полностью).
Прикрепленные файлы для скачивания:

Нет доступа к просмотру комментариев.

^
Регистрация
Регистрируясь, вы принимаете правила сайта. Если вы не получили код подтв. регистрации - не забудьте проверить папку спам.
Логин*
Email*
Пароль*
Подтверждение пароля*
 
Логин*
Код*
 
×
Восстановление пароля
Пожалуйста, заполните поля, после чего вы получите код подтверждения на ваш Email. Если код не пришел в течении нескольких минут - проверьте папку спам.
Логин

или Email
Логин*
Код подтверждения*
Новый пароль*
Подтверждение пароля*
×
Авторизация
  • Используйте вашу учетную запись на Facebook.com для входа на сайт.
  • Используйте вашу учетную запись VKontakte для входа на сайт.
  • Используйте вашу учетную запись Google для входа на сайт.
Авторизуйтесь с помощью соц. сети или с помощью аккаунта на сайте:
×