Е. А. Снижко, Н. А. Флерова
![]()
|
Контрольные вопросы 1. Какая модель освещения используется в OpenGL? 2. Какие виды освещения можно установить в программе OpenGL? 3. Чем определяется цвет поверхности объекта? 4. Какие команды используются для установки источника освещения? 58 5. Сколько источников освещения можно определить в про- грамме OpenGL? 6. Как влияют свойства материала на видимый цвет объекта? 7. В чем заключаются различия между направленными и по- зиционными источниками освещения? 8. В чем заключается эффект ослабления? Лабораторная работа № 7 ТЕКСТУРЫ: РЕЖИМЫ ФИЛЬТРАЦИИ, РЕЖИМЫ ВЗАИ- МОДЕЙСТВИЯ ТЕКСТУРЫ С ОБЪЕКТОМ, АВТОМАТИ- ЧЕСКАЯ ГЕНЕРАЦИЯ ТЕКСТУРНЫХ КООРДИНАТ Цель работы – дать представление о возможностях наложе- ния текстур на поверхности объектов средствами OpenGL. Необходимые теоретические сведения Текстура – одномерное, двумерное или трехмерное изобра- жение, которое имеет множество ассоциированных с ним пара- метров, определяющих, каким образом будет производиться на- ложение изображения на поверхность. Проще говоря, текстура – это изображение, накладываемое на поверхность. С физической точки зрения текстура – массив данных, например цветовых, све- товых или цветовых и альфа. Каждый элемент этого массива на- зывается текселем. Текстурные координаты – координаты тек- селя, назначаемого вершине. Общепринятые имена для текстурных координат – s, t, r, q. Для использования текстур необходимо выполнить следую- щие действия:* 1. Подготовка изображения для использования в текстуре. Загрузка изображения из файла. 2. Создание текстуры: • генерация уникального имени текстуры ∗ , • первичное связывание * , • связывание изображения с текстурой * , • установка режимов фильтрации текстуры, ∗ Звездочкой обозначены обязательные пункты. 59 • установка параметров взаимодействия объекта с накла- дываемой текстурой, • установка режима мозаичного наложения текстуры, • автоматическая генерация текстурных координат, эффект отражения. 3. Использование текстуры: • выбор текстуры для использования (вторичное связыва- ние), • согласование геометрических и текстурных координат, • создание эффекта отражения с помощью текстур. Подготовка изображения для использования в текстуре. Первый этап выполняется при инициализации OpenGL. OpenGL имеет свой формат хранения изображений. Подготовительный этап заключается в том, чтобы преобразовать изображение в формат OpenGL. В библиотеке GLAUX имеется функция, кото- рая считывает изображение из DIB или BMP файла и автоматиче- ски преобразовывает его к формату OpenGL: AUX_RGBImageRec* auxDIBImageLoad(strFile); Функция возвращает указатель на структуру типа AUX_RGBImageRec, которая хранит само изображение и его ос- новные параметры – ширину и высоту: struct AUX_RGBImageRec { unsigned char *data; // изображение GLint sizeX; // ширина изображения GLint sizeY; // высота изображения }; Передаваемое значение – путь к файлу с изображением. Пример использования функции auxDIBImageLoad – загрузка изображения из файла sky.bmp в объект структуры ImageSky: AUX_RGBImageRec *ImageSky; ImageSky = auxDIBImageLoad(“sky.bmp”); Создание текстуры. Этот этап, как и подготовка изображе- ния, обычно выполняется во время инициализации OpenGL. Для того чтобы разрешить текстурирование, используется функция glEnable(GL_TEXTURE_2D); 60 Единственный параметр этой функции определяет тип тек- стур, используемых в программе. Обычно этот параметр прини- мает значение GL_TEXTURE_2D. Генерация уникального имени текстуры. Каждая текстура, которая используется в OpenGL должна иметь свое уникальное имя – идентификатор типа GLuint. Для автоматической генера- ции этого идентификатора служит функция void glGenTextures(GLsizei n, GLuint *textures); Передаваемые параметры: n – количество генерируемых идентификаторов; textures – массив, куда будут записаны cгене- рированные идентификаторы Пример генерации уникальных идентификаторов в первом случае для одной текстуры, во втором – для пяти текстур: GLuint SingleTex; Gluint ArrayTex[5]; glGenTextures(1, &SingleTex);// Генерация одного // идентификатора glGenTextures(5, &ArrayTex); // Генерация пяти // идентификаторов Первичное связывание. Перед тем как задать конкретное изображение текстуре, необходимо произвести операцию пер- вичного связывания. При этом создается новый объект текстуры, и переданное имя текстуры ассоциируется с ним. Реализуется это посредством вызова функции void glBindTexture (GLenum target, GLuint texture), target задает целевой объект, с которым связывается текстура и может принимать значения GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D. texture – идентификатор текстуры. Пример первичного связывания создает текстурный объект и сопоставляет с ним идентификатор SingleTex. glBindTexture(GL_TEXTURE_2D, SingleTex); Связывание изображения с текстурой. Конкретное изо- бражение ассоциируется с текстурой с помощью функции glTexImage2D. 61 Для изображения, подготовленного функцией auxDIBImageLoad, необходимо в качестве параметра target ис- пользовать значение GL_TEXTURE_2D. Изображение, которые Вы используете, должно иметь ширину и высоту, кратную степе- ни двойки, ширина границы текстуры тоже должна быть степе- нью двойки. Если Вы не используете границу текстуры, то в качестве параметра border следует указать 0. Формат цвета пик- селя – GL_RGB. Внутренний формат – число 3. Количество уровней дета- лизации можно установить в 0. Ширина, высота и само изобра- жение определяются из объекта типа AUX_RGBImageRec, подго- товленного с помощью функции auxDIBImageLoad: void glTexImage2D( GLenum target, // GL_TEXTURE_2D GLint level, // Уровень детализации GLint internalformat, // Внутренний формат GLsizei width, // ширина изображения GLsizei height, // высота изображения GLint border, // ширина границы GLenum format, // формат цвета пикселя GLenum type, // тип данных в массиве pixels const GLvoid *pixels); // указатель на изображение П р и м е р. Создаем текстуру с идентификатором SingleTex и изображением ImageSky: glTexImage2D(GL_TEXTURE_2D, 0, 3, ImageSky->sizeX, TypeGL_RGBImage->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TypeGL_RGBImage->data); Режимы фильтрации. При различии размеров текстуры и размеров объекта, на который она накладывается, используются различные режимы фильтрации: режим без сглаживания, линей- ная фильтрация, мип-мэп-наложение. Использование режима без сглаживания позволяет добиться максимальной производительности, однако изображение при этом будет выглядеть неестественно. Этот режим рекомендовано применять только на очень слабых машинах. 62 Для задания режимов фильтрации используется функция glTexParameteri: void glTexParameteri(GLenum target, GLenum pname, GLint param); Первый параметр определяет тип текстуры (в нашем случае GL_TEXTURE_2D), второй – устанавливаемые параметры. При установке параметров уменьшающего фильтра (размер текстуры больше размера поверхности на которую она накладывается) этот параметр принимает значение GL_TEXTURE_MIN_FILTER, а при установке параметров увеличивающего фильтра – GL_TEXTURE_MAX_FILTER. Последний параметр определяет значение параметра pname. При использовании фильтра без сглаживания он принимает зна- чение GL_NEAREST Пример задания уменьшающего и увеличивающего фильтра без сглаживания: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MA Х _FILTER, GL_NEAREST); Использование линейной фильтрации позволяет заметно улучшить качество изображения, однако производительность при этом снижается, так как этот режим требует определенных вы- числений. В режиме увеличения/уменьшения используется взве- шенная сумма массива текселей 2х2, которые находятся ближе всего к отображаемому пикселю. Вызов функции glTexParameteri для установки режима фильтрации аналогичен режиму без сглаживания, за исключени- ем последнего параметра – он принимает значение GL_LINEAR Пример задания уменьшающего и увеличивающего фильтра линейной фильтрации: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MA Х _FILTER, GL_LINEAR); 63 Мип-мэп-наложение. При использовании этого метода OpenGL создает набор картинок разного размера (от исходного до размера в 1х1 тексель). Во время работы программы автома- тически выбирается картинка наиболее подходящего размера. При использовании этого способа возможно несоблюдение усло- вия, что высота и ширина изображения должны быть степенью двойки. Существуют отличия в связывании изображения с тек- стурой (см. п. 2). Этот способ фильтрации дает наилучшее изо- бражение, однако является наиболее затратным с точки зрения производительности. Пример использования связывания изображения с текстурой с последующим включением режима фильтрации – мип-мэп- наложение: gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TypeGL_RGBImage->sizeX, TypeGL_RGBImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TypeGL_RGBImage->data); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MA Х _FILTER, GL_LINEAR_MIPMAP_LINEAR); Параметры, передаваемые в функцию gluBuild2Dmipmaps, аналогичны передаваемым в функцию glTexImage2D. Установка параметров взаимодействия объекта с накла- дываемой текстурой. В OpenGL существует возможность сме- шивать цвет накладываемой текстуры с исходным цветом объек- та. Для этого необходимо вызвать функцию glTexEnv: void glTexEnv(Glenum target, Glenum pname, GLType param); taget – первый параметр – определяет конфигурацию тексту- ры и должен быть равен GL_TEXTURE_ENV; pname определяет символическое имя конфигурации текстуры и должен быть равен GL_TEXTURE_ENV_MODE; param – символическая константа, для которой допустимы значения GL_MODULATE, GL_DECALL, GL_BLEND. 64 При использовании GL_MODULATE цвет текстуры как бы сливается с цветом объекта, при режиме DECALL цвет объекта соответствует цвету накладываемой текстуры. П р и м е р. В первом случае результирующий цвет объекта складывается из цвета объекта и цвета текстуры, во втором ре- зультирующий цвет – это цвет текстуры: // Слияние цветов glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Цвета текстуры glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECALL); Установка режима мозаичного (тайлового) наложения текстуры. Иногда возникает необходимость в повторении тек- стуры, например при отрисовке кирпичной стены. OpenGL пре- доставляет такую возможность, достаточно только выполнить два условия: а) разрешить режим повторения текстуры. Режим повторения задается отдельно для вертикальной и для горизонтальной оси: GlTexParametri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GlTexParametri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); Последний параметр определяет режим наложения текстуры. При значении GL_REPEAT текстура будет повторяться при на- ложении на объект. Если вместо последнего параметра – GL_REPEAT – использовать GL_CLAMP, текстура будет растя- гиваться при наложении на накладываемую поверхность; б) задать координаты текстуры > 1.0, например 4.0. В этом случае текстура будет повторена на накладываемой поверхности четыре раза. Автоматическая генерация текстурных координат, эф- фект отражения. С помощью текстурирования в OpenGL мож- но реализовать эффект отражения окружающих предметов от блестящих поверхностей. Ниже приведен пример задания режима зеркального отражения. В двух строчках определяются парамет- 65 ры генерации текстурных координат. В данном случае текстур- ные координаты вычисляются в сфере вокруг позиции образа. При использовании автоматической генерации текстурных коор- динат необходимо в качестве фильтра использовать мип-мэпы: gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TypeGL_RGBImage->sizeX, TypeGL_RGBImage->sizeY, GL_RGB, GL_UNSIGNED_BYTE, TypeGL_RGBImage->data); glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); Использование текстуры. Этот этап выполняется непосред- ственно в функции прорисовки сцены. Выбор текстуры для использования (вторичное связыва- ние). Для использования текстуры в программе ее надо сделать активной. Этот процесс и называется вторичным связыванием. Вторичное связывание, как и первичное, выполняется с помощью функции void glBindTexture (GLenum target, GLuint textureName); target определяет тип текстуры (GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D). Этот параметр должен совпадать с тем, который был использован в операции первичного связывания; textureName – идентификатор текстуры. Пример вторичного связывания – команда делает активной текстуру с идентификатором SingleTex: glBindTexture(GL_TEXTURE_2D, SingleTex); Согласование геометрических и текстурных координат. При прорисовке объекта, на который накладывается текстура, необходимо согласовать текстурные координаты с геометриче- скими. Например, при наложении текстуры на прямоугольный объект Вы должны отобразить правый верхний угол текстуры в правый верхний угол объекта, правый нижний угол текстуры в правый нижний угол объекта и т.д. Текстурные координаты являются частью данных, связанных с вершинами многоугольника (рис. 7). Для установки текстурных координат используется функция 66 glTexCoord2f(GLfloats,GLfloat t); s определяет горизонтальную текстурную координату, t – верти- кальную. Пример наложения текстуры с растяжением на прямо- угольный объект (рис. 8). glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-1.,-1., 0.); // левый нижний угол glTexCoord2f(1.0, 0.0); glVertex3f( 5.,-1., 0.); // правый нижний угол glTexCoord2f(1.0, 1.0); glVertex3f( 5., 3., 0.); // правый верхний угол glTexCoord2f(0.0, 1.0); glVertex3f(-1., 3., 0.); // левый верхний угол glEnd(); 3.0 5.0 -1.0 -1.0 y x z Рис. 8. Наложение текстуры на прямоугольный объект s t 0.0 0.0 1.0 1.0 0.5 0.5 Рис. 7. Система текстурных координат 67 Пример наложения текстуры на треугольник (рис. 9).В дан- ном примере используется только левая нижняя часть текстуры glBegin(GL_TRIANGLES); glTexCoord2f(0.0, 0.0); glVertex3f(-2.,-1., 0.); // левая нижняя вершина glTexCoord2f(0.5, 0.0); glVertex3f( 2.,-1., 0.); // правая нижняя вершина glTexCoord2f(0.25, 0.5); glVertex3f( 0., 3., 0.); // верхняя вершина glEnd(); Пример мозаичного (тайлового) покрытия текстурой (рис. 10). Координаты прямоугольника совпадают с координата- ми на рис. 8. Текстура будет повторена по горизонтальной оси три раза, по вертикальной – два раза. Для возможности повторе- ния текстуры этот режим должен быть активирован с помощью команд: y x z 2.0 -2.0 - 1.0 3.0 Рис. 9. Наложение текстуры на треугольник Рис. 10. Мозаичное покрытие объекта текстурой -1.0 x z -1.0 3.0 5.0 y 68 GlTexParametri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); GlTexParametri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBegin(GL_QUADS); glTexCoord2f(0.0, 0.0); glVertex3f(-1.,-1., 0.); // левый нижний угол glTexCoord2f(3.0, 0.0); glVertex3f( 5.,-1., 0.); // правый нижний угол glTexCoord2f(3.0, 2.0); glVertex3f( 5., 3., 0.); // правый верхний угол glTexCoord2f(0.0, 2.0); glVertex3f(-1., 3., 0.); // левый верхний угол glEnd(); Пример создания с помощью текстур эффекта отражения. Необходимо разрешить OpenGL использовать автоматически сгенерированные координаты. Параметры, с помощью которых эти координаты будут генерироваться, хранятся в текстурном объекте, созданном на втором этапе: //1 - разрешаем автогенерацию текстурных // координат по оси S //2 - разрешаем автогенерацию текстурных // координат по оси T glEnable(GL_TEXTURE_GEN_S); // 1 glEnable(GL_TEXTURE_GEN_T); // 2 glBegin(GL_QUADS); glVertex3f(-1.,-1., 0.); // левый нижний угол glVertex3f( 5.,-1., 0.); // правый нижний угол glVertex3f( 5., 3., 0.); // правый верхний угол glVertex3f(-1., 3., 0.); // левый верхний угол glEnd(); // 3 - запрещаем автогенерацию текстурных // координат по оси S //4 - запрещаем автогенерацию текстурных // координат по оси T glEnable(GL_TEXTURE_GEN_S); // 3 glEnable(GL_TEXTURE_GEN_T); // 4 69 Задания к работе 1. Подготовить изображение к использованию в качестве текстуры. В качестве изображения выбрать любое из имеющихся на компьютере. При отсутствии таковых изображение создается в графическом редакторе. 2. Создать текстурный объект. 3. Настроить параметры текстурных объектов в соответст- вии с вариантом. Номер варианта Увеличивающий фильтр Уменьшающий фильтр Взаимодействие с поверхностью 1 Линейная фильтрация Без сглаживания Смешивание 2 Без сглаживания Линейная фильтрация Без смешивания 3 Мип-мэп-наложение Без сглаживания Без смешивания 4 Линейная фильтрация Линейная фильтрация Смешивание 5 Мип-мэп-наложение Линейная фильтрация Без смешивания 4. Изобразить объект в соответствии с вариантом. Номер варианта Вид объекта Номер варианта Вид объекта 1 4 2 5 3 70 5. Наложить текстуры на созданный геометрический объект. 6. Реализовать изменение параметров текстуры при нажатии клавиш в соответствии с вариантом. Номер варианта Вносимые изменения 1 Установка уменьшающего фильтра в режим линейной фильтрации. Вращение объекта вокруг оси Х. 2 Разрешение тайлового покрытия текстурой. Изменения количества повторения текстуры. Вращение объекта вокруг оси Z. 3 Изменение режима взаимодействия с поверхностью в режим смеши- вания. Вращение текстуры вокруг оси Y. 4 Установка увеличивающего и уменьшающего фильтра. Вращение текстуры вокруг оси Z. 5 Создание эффекта зеркального отражения. Вращение текстуры во- круг осей X, Y. |