14574

Работа с изображением. Наложение текстуры

Лабораторная работа

Информатика, кибернетика и программирование

Лабораторная работа №5 Работа с изображением. Наложение текстуры. 1.Работа с изображением Существует множество графических форматов bmp pcx gif jpeg и прочие. OpenGL напрямую не поддерживает не один из них. В OpenGL нет функций чтения/записи графических файлов. Но подде

Русский

2013-06-08

67 KB

3 чел.

Лабораторная работа №5

Работа с изображением. Наложение текстуры.

      1.Работа с изображением

Существует множество графических форматов - bmp, pcx, gif, jpeg и прочие. OpenGL напрямую не поддерживает не один из них. В OpenGL нет функций чтения/записи графических файлов. Но поддерживается работа с массивами пикселей. Вы загружаете графический файл, используя библиотеки других фирм, в память и работаете с ними средствами OpenGL. В массиве данные о пикселах могут располагаться разными способами: RGB, BGR, RGBA; могут присутствовать не все компоненты; каждый элемент массива может занимать один байт, два, четыре или восемь; выравнивание может быть по байту, слову или двойному слову. В общем, форматов расположения данных о графическом изображении в памяти очень много.

Наиболее часто применяется формат, в котором информация о каждом пикселе хранится в формате RGB и занимает три байта, выравнивание по байту. В Auxiliary Library есть функция auxDIBImageLoad(LPCSTR), которая загружает в память bmp-файл и возвращает указатель на структуру:

 typedef struct _AUX_RGBImageRec {

  GLint sizeX, sizeY;

  unsigned char *data;

} AUX_RGBImageRec;   

     В OpenGL имеются функции для вывода массива пикселей на экран(glDrawPixels), копирования(glCopyPixels), масштабирования(gluScaleImage). Здесь мы рассмотрим только glDrawPixels. Все остальные функции работы с изображениями устроены похожим образом. Для того, чтобы отобразить графический файл в окне OpenGL, вы должны загрузить его в память, указать выравнивание, установить точку, с которой начинается вывод изображения, и вывести его на экран. Создайте новый проект. Объявите глобальную переменную -

AUX_RGBImageRec *image

Перед вызовом функции glutMainLoop() в функции main вставьте строку:

image = auxDIBImageLoad("photo.bmp");

     Выравнивание устанавливается вызывом функции glPixelStorei с параметром GL_UNPACK_ALIGNMENT и вторым параметром - целым числом, которое указывает выравнивание.

void glPixelStore{if}(GLenum pname, TYPEparam); 

Функция установки способа хранения пикселов для выполнения следующих функций: glDrawPixels(), glReadPixels(), glBitmap(), glPolygonStipple(), glTexImage1D(), glTexImage2D(), glTexSubImage1D(), glTexSubImage2D(), and glGetTexImage().

Изображения выводятся прямо на экран. Поэтому все происходит в двухмерных координатах. Позиция, с которой начинается вывод изображения, указывается при помощи функции glRasterPos2d(x,y).

void glRasterPos{234}{sifd}(TYPE x, TYPE y, TYPE z, TYPE w);
void
glRasterPos{234}{sifd}v(TYPE *coords); 

Функция установки текущей позиции растра: x, y, z, w- однородные координаты, определяющие позицию растра. Если используется функция  glRasterPos2*(), то z подразумевается равным 0, а равным 1.

  Также вы можете установить размер пикселя, вызвав функцию glPixelZoom. Первый параметр этой функции - ширина, второй - высота пикселя. Вызов этой функции с аргументами (1,1), что соответствует нормальному пикселю. Замените (1,1) на (3,2) и вы увидите, как картинка растянется в три раза по горизонтали и в два раза по вертикали. Это случилось, потому что теперь каждый пиксель изображения соответствует прямоугольнику 3х2 в окне.

void glPixelZoom(GLfloat zoomx, GLfloat zoomy); 

Функция устанавливает фактор увеличения/уменьшения при выполнении операции записи пикселя в буфер кадра (glDrawPixels() или glCopyPixels()) по x и y координатам.  По умолчанию , zoomx и zoomy равны  1.0. Если оба значения равны 2, то каждый пиксель исходного изображения выводится в виде 4-х пикселей в буфере кадра. Отрицательное значение фактора выполняет зеркальное отображение изображения относительно текущей позиции растра.

И наконец, вывод осуществляет функция glDrawPixels. Первые два параметра - это ширина и высота. Далее, вы указываете формат, в котором хранится информация в памяти, и тип элементов массива. Последним указывается массив данных.

void glDrawPixels(GLsizei width, GLsizei height, GLenum format,
GLenum
type, const GLvoid *pixels); 

Функция выводит изображение прямоугольного массива пикселей размером width на height. Прямоугольник выводится, начиная с левого нижнего угла изображения в текущей позиции растра, format и type параметры могут принимать одно из значений, приведенных в таблицах Table 8-1 и Table 8-2 Руководства программиста по OpenGL. Массив pixels содержит данные о пикселях, которые должны быть выведены.

В функцию display вставьте следующий код:

 

glRasterPos2d(-4.5,-3);                    // нижний левый угол

glPixelZoom(1,1);

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);         // выравнивание

glDrawPixels(image->sizeX, image->sizeY, // ширина и высота

               GL_RGB, GL_UNSIGNED_BYTE,      // формат и тип

                         image->data);     // сами данные

     Также в OpenGL имеется функция glBitmap для отображения битовых массивов. Битовый массив - это последовательность байт, которые кодируют картинку из двух цветов.

2.Наложение текстуры.

     Одного вывода изображений недостаточно для создания полноценных трехмерных сцен. Часто возникает потребность накладывать изображение на трехмерные объекты и поворачивать/сдвигать их. Для этих целей существую текстуры. Также текстуры помогут вам покрыть весь объект в виде мозаики. Скажем, когда у вас имеется кирпичная стена, то вам не надо загружать изображение с кучей кирпичей. Достаточно загрузить один кирпич и указать, что эту текстуру нужно размножить по всей плоскости.

Для того, чтобы наложить текстуру на объект, вы должны:

  1.  Загрузить графический файл в память
  2.  Создать имя-идентификатор текстуры
  3.  Сделать его активным
  4.  Создать саму текстуру в памяти
  5.  Установить параметры текстуры
  6.  Установить параметры взаимодействия текстуры с объектом
  7.  Связать координаты текстуры с объектом

    1. Загрузка графического файла выполняется в соответствии с п. 1. лабораторной работы.

2. Создать имя-идентификатор текстуры

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

void glGenTextures(GLsizei n, GLuint*textures)

надо создать n идентификаторов для используемых текстур, которые будут записаны в массив textures.

 Для единственной текстуры в приложении можно использовать следующую последовательность операторов:

static GLuint texName;

glGenTextures(1, &texName);

3. Сделать имя текстуры активным

Перед началом определения свойств очередной текстуры следует вызвать команду

void glBindTexture(GLenum target, GLuint texture)

где target может принимать значения GL_TEXTURE_1D или GL_TEXTURE_2D, а параметр texture должен быть равен идентификатору той текстуры, к которой будут относиться последующие команды. Для того, чтобы в процессе рисования сделать текущей текстуру с некоторым идентификатором, достаточно опять вызвать команду glBindTexture() c соответствующим значением target и texture. Таким образом, команда glBindTexture() включает режим создания текстуры с идентификатором texture, если такая текстура еще не создана, либо режим ее использования, то есть делает эту текстуру текущей. Например,

glBindTexture(GL_TEXTURE_2D, texName);

4. Создание текстуры в памяти

    Теперь мы должны создать саму текстуру в памяти. Массив байт в структуре AUX_RGBImageRec не является еще текстурой, потому что у текстуры много различных параметров. Создав текстуру, мы наделим ее определенными свойствами. Среди параметров текстуры вы указываете уровень детализации, способ масшабирования и связывания текстуры с объектом. Уровень детализации нужен для наложения текстуры на меньшие объекты, т.е. когда площадь на экране меньше размеров изображения. Нулевой уровень детализации соответствует исходному изображению размером 2nx2m, первый уровень - 2n-1x2m-1, k-ый уровень - 2n-kx2m-k. Число уровней соответствует min(n,m). Для создания текстуры имеется две функции glTexImage[1/2]D и gluBuild[1/2]DMipmaps.

glTexImage2D(                 gluBuild2DMipmaps(

 GLenum target,                 GLenum target,   

 GLint lavel,                   GLint components,    

 GLint components,              GLsizei width,

 GLsizei width,                 GLsizei height,

 GLsizei height,                GLenum format,

 GLint border,                  GLenum type,

 GLenum format,                 const GLvoid* pixels)        

 GLenum type,

 const GLvoid* pixels)

     Основное различие в том, что первая функция создает текстуру одного определенного уровня детализации и воспринимает только изображения , размер которых кратен степени двойки. Вторая функция более гибкая. Она генерирует текстуры всех уровней детализации. Также эта функция не требует, чтобы размер изображения был кратен степени двойки. Она сама сожмет/растянет изображение подходящим образом, хотя возможно окажется, что и не вполне подходящим. Я воспользуюсь функцией glTexImage2D. Первый параметр этой функции должен быть GL_TEXTURE_2D. Второй - уровень детализации. Нам нужно исходное изображение, поэтому уровень детализации - ноль. Третий параметр указывает количество компонентов цвета. У нас изображение хранится в формате RGB. Поэтому значение этого параметра равно трем. Четвертый и пятый параметры - ширина и высота изображения. Шестой - ширина границы; у нас гарницы не будет, поэтому значение этого параметра - ноль. Далее, седьмой параметр - формат хранения пикселей в массиве - GL_RGB и тип - GL_UNSIGNED_BYTE. И наконец, восьмой параметр - указатель на массив данных. Еще вы должны вызвать функцию glPixelStorei и задать, что выравнивание в массиве данных идет по байту.

Добавьте следующий код в функцию main.

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

glTexImage2D(GL_TEXTURE_2D, 0, 3,

            photo_image->sizeX,

            photo_image->sizeY,

            0, GL_RGB, GL_UNSIGNED_BYTE,

            photo_image->data);

     Аналогичный результат можно получить, вставив вызов gluBuild2DMipmaps с параметрами, указанными ниже.

gluBuild2DMipmaps(GL_TEXTURE_2D, 3,

                 photo_image->sizeX,

                 photo_image->sizeY,

                 GL_RGB, GL_UNSIGNED_BYTE,

                 photo_image->data);

5. Установить параметры текстуры

    Теперь нужно установить параметры текстуры. Для этого служит функция 

glTexParameter[if](GLenum target, GLenum pname, GLenum param)

     Первый параметр принимает значение GL_TEXTURE_1D или GL_TEXTURE_2D. Второй - pname - определяет параметр текстуры, который вы будете изменять. И третий параметр - это устанавливаемое значение. Если вы воспользовались gluBuild2DMipmaps вместо glTexImage2D, то вам не надо устанавливать следующие параметры, т.к. уже сформированы текстуры всех уровней детализации, и OpenGL сможет подобрать текстуру нужного уровня, если площадь объекта не совпадает с площадью текстуры. В противном случае, вы должны добавить следующие строки:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

     Вы указали, что для уменьшения и увеличения текстуры используется алгоритм GL_NEAREST. Это означает, что цветом пикселя объекта, на который накладывается текстура, становится цвет ближайшего пикселя элемента текстуры. Вместо GL_NEAREST можно указать GL_LINEAR, т.е. цвет элемента объекта будет вычисляться как среднее арифметическое четырех элементов текстуры. Имеются еще четыре алгоритма вычисления цвета элемента объекта. Их можно устанавливать, когда вы создали текстуру со всеми уровнями детализации, т.к. применяют алгоритмы GL_NEAREST и GL_LINEAR к одному или двум ближайшим уровням детализации.
    

6. Установка параметров взаимодействия текстуры с объектом

 Вы можете установить взаимодействие текстуры с объектом. Тут имеются два режима при использовании трех компонентов цвета. Первый режим, установленный по умолчанию, когда у вас учитывается цвет объекта и цвет текстуры. Результирующий цвет получается перемножением компонентов цвета текстуры на компоненты цвета объекта. Скажем, если цвет текстуры - (r,g,b), а цвет объекта, на который она накладывается, - (r0,g0,b0), то результирующим цветом будет - (r*r0,g*g0,b*b0). В случае, если цвет объекта черный - (0,0,0), то вы не увидите на нем текстуру, так как она вся будет черной. Второй режим взаимодействия, когда цвет объекта не учитывается. Результирующим цветом будет цвет текстуры. Эти параметры можно установить следующим образом.

glTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE)

glTexEnv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)

     По умолчанию, как я уже сказал, является режим GL_MODULATE. На этом заканчивается создание текстуры.

6. Связь координат текстуры с объектом

Осталось связать координаты текстуры с координатами объекта.

void glTexCoord{1234}{sifd}(TYPEcoords);
void
glTexCoord{1234}{sifd}v(TYPE *coords); 

Функция устанавливает соответствие текущих координат текстуры (s, t, r, q) с координатами вершины примитива OpenGL, следующей за этой командой. При исползовании функции glTexCoord2*() небходимо определить только координаты s и t.

Например, чтобы связать координаты текстуры с вершинами прямоугольника, можно использовать следующую последовательность команд в функции display:

glEnable(GL_TEXTURE_2D);

 glColor3d(1,1,1);

glBindTexture(GL_TEXTURE_2D, space_tex );

 glBegin(GL_QUADS);

    glTexCoord2d(0,0); glVertex3d(-5,-5, -0.1);

    glTexCoord2d(0,1); glVertex3d(-5, 5, -0.1);

    glTexCoord2d(1,1); glVertex3d( 5, 5, -0.1);

    glTexCoord2d(1,0); glVertex3d( 5,-5, -0.1);

 glEnd();

 glDisable(GL_TEXTURE_2D);

glTexCoord2d сопоставляет координаты текстуры вершинам четырехугольника. Нижний левый угол текстуры имеет координаты (0,0), а верхний правый - (1,1).

 Порядок выполнения работы.

  1.  Получить средствами OpenGL  изображение .bmp- файла, заданного преподавателем.
  2.  Наложить изображение этого файла на все грани куба из лабораторной работы №4.


 

А также другие работы, которые могут Вас заинтересовать

4401. Космологические модели вселенной 87.5 KB
  Космологические модели вселенной ЧТО ТАКОЕ КОСМОЛОГИЯ? Современная космология - это астрофизическая теория структуры и динамики изменения Метагалактики, включающая в себя и определенное понимание свойств всей Вселенной. Космология основывается на ас...
4402. Вивчення впливу зовнішнього оточення організації на її діяльність 111 KB
  Вступ Не існує жодної організації, що не мала б зовнішнього оточення і не знаходилася б з ним у стані постійної взаємодії. Успіх будь-якої організації залежить не тільки від факторів діючих всередині організації, але, вирішальним чином, залежи...
4403. Розрахунки чеками та векселями 51.5 KB
  Чек — грошовий документ встановленої форми, що містить беззаперечне письмове розпорядження власника рахунка (клієнта) банкові, який обслуговує його, сплатити певну суму грошей пред'явникові чека або іншій вказаній у чеку особі
4404. Агропомышленный комплекс Новосибирской области 92.5 KB
  Введение Новосибирская область: государственно-территориальное образование, входящее в состав Российской Федерации на правах ее равноправного субъекта, расположена в географическом центре страны, в юго-восточной части Западно-Сибирской равнины, глав...
4405. Фанализ - филосовско-аналитическая теория истины 152 KB
  Эта работа была задумана для рассмотрения более объективной оценки окружающего мира. Здесь рассматриваются более двадцати вопросов, наиболее значимых, при объяснении такого подхода поиска истины как Фанализ. Этот взгляд должен дать толчок для самора...
4406. Разработка тягового и топливно-экономического расчета автомобиля 1.09 MB
  В курсе теории автомобиля тяговый и топливно-экономический расчет является одним из важнейших разделов. Этот расчет позволяет по некоторым заданным параметрам определить остальные конструктивные и эксплуатационные параметры...
4407. Адвокат в гражданском процессе 268.5 KB
  Адвокат в гражданском процессе Введение Современный человек постоянно сталкивается с ситуациями, в которых ему необходимо руководствоваться теми или иными правовыми предписаниями, то есть законодательно закрепленными общеобязательными правилами пове...
4408. Административная ответственность за нарушение налогового законодательства 311 KB
  Административная ответственность за нарушение налогового законодательства Введение Процесс формирования норм налогового законодательства выявил особую актуальность установления ответственности за налоговые нарушения. Прямая зависимость государственн...
4409. Адвокатура Украины. Организация современной адвокатуры Украины 63 KB
  Адвокатура Украины. Организация современной адвокатуры Украины. Принципы и гарантии адвокатской деятельности. Согласно Закону адвокатура Украины является добровольным профессиональным общественным объединением, призванным содействовать защите прав, свобо...