Top.Mail.Ru

Уроки OpenGL. Часть 5. Создание и наложение текстуры.

Как уже понятно из названия статьи, речь пойдет об использовании текстур в OpenGL. В прошлом уроке мы создали куб и добавили возможность вращать его вокруг осей координат. Сегодня давайте попробуем наложить текстуры на грани куба и получить некое подобие игральной кости.

Итак, возьмем за основу проект из предыдущей статьи, и для начала нужно добавить в него изображения, на базе которых впоследствии мы создадим текстуры. Я не стал особо заморачиваться, просто нарисовал по-быстрому в paint'е 6 картинок, по одной для каждой грани куба. Получилось вот так:

Пример наложения текстур в OpenGL.

Тем, кто как и я, использует Qt Creator теперь необходимо добавить эти файлы в проект. Для этого нужно создать пустой файл ресурсов и прописать в нем пути для всех используемых изображений. Итак, картинки готовы, задача понятна, давайте приступать к реализации. И первым делом нам необходимо, собственно, создать текстуры из изображений. Добавим в проект функцию generateTextutes():

void MainScene::generateTextures()
{
	glGenTextures(6, textures);

	QImage currentTexture;
	currentTexture.load(":/cubeOne.jpg");
	currentTexture = QGLWidget::convertToGLFormat(currentTexture);
	glBindTexture(GL_TEXTURE_2D, textures[0]);
	glTexImage2D(GL_TEXTURE_2D, 0, 3, (GLsizei)currentTexture.width(), (GLsizei)currentTexture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, currentTexture.bits());
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	
	// Далее генерация остальных текстур...

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

Давайте разбираться, что тут происходит...

Первым делом вызываем функцию glGenTextures() - она генерирует специальные имена для каждой из текстур и помещает их в массив, который мы передаем в качестве одного из аргументов. А первый аргумент - количество текстур, которые нам понадобятся (в данном случае у нас 6 граней, значит передаем в функцию аргумент "6"). Эта функция вызывается только один раз, в самом начале функции generateTextures(). И, кстати, не забудьте объявить массив в нашем классе MainScene:

GLuint textures[6];

С этим все понятно, переходим дальше. Теперь мы создаем объект класса QImage и загружаем в него наше изображение. Функция glBindTexture() делает активной текстуру с номером, соответствующим аргументу функции. В данном случае это текстура для первой грани (textures[0]). Вызовом этой функции мы как бы показываем OpenGL, что дальнейшие действия нужно производить именно с той текстурой, которую мы выбрали. Поэтому вызов glTexImage2D() произведет генерацию текстуры, соответствующей номеру textures[0] (напоминаю, в этом массиве у нас хранятся уникальные номера-идентификаторы для каждой из текстур проекта).

Функция glTexImage2D() принимает на вход кучу аргументов, так что давайте рассмотрим каждый из них в отдельности:

  • первый параметр говорит о том, что мы будем работать с 2D текстурой
  • второй параметр - уровень детализации, у нас 0
  • третий - 3 - число цветовых компонент - RGB
  • четвертый, пятый - ширина и высота текстуры, у нас они определяются автоматически
  • пятый - относится к границе текстуры, его просто оставляем нулевым
  • шестой, седьмой - дают OpenGL информацию о цветах и типе данных исходного изображения
  • и, наконец, седьмой параметр передает OpenGL сами данные изображения, из которых нужно формировать текстуру.

На этом создание текстуры заканчивается, но нужно еще настро