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.


 

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

54648. МИ - ОЛІМПІЙЦІ 199.5 KB
  Мета: популяризація олімпійських видів спорту; пропаганда здорового способу життя; формування моральних якостей.
54649. Sport Events. Olympic Games 468.5 KB
  Dear pupils. I am glad to see you here. I am sure you are ready for active work. Our topic today is “Sport. Olympic Games”. By the end of the lesson you should learn more about International Olympic Movement and about Olympic Games and the first marathon. I see that you are happy and you know it because your faces surely show it. So let’s sing one of our favourite songs.
54650. Розв’язання задач підвищеної складності у процесі підготовки учнів до олімпіад із фізики 1.25 MB
  Опанування учнями середньої школи знань із фізики потребує розвязання задач. Таким чином формуються допитливість самостійність інтерес до навчання розвивається вміння аналізувати явища.
54651. РУКОВОДСТВО ПО КОМПЬЮТЕРНОЙ БЕЗОПАСНОСТИ И ЗАЩИТЕ ИНФОРМАЦИИ ДЛЯ БОЛЬШИХ БОССОВ 816 KB
  Но почему ты думаешь что защита твоей собственной информации любой деловой или личной это менее интимное дело Увы друг мой защита твоей информации или хотя бы чёткое понимание того что это такое и как подобная защита должна строиться это ТВОЁ ЛИЧНОЕ ДЕЛО Не Cos Nоstr хотя твои проблемы могут стать и Нашим Делом тоже а Cos Tu Твоё Дело Разумеется тебе не хочется вникать во все эти тонкости. В этом конечно есть определённая лоrика однако безопасность твоей информации это и есть Большая Проблема уверяю тебя. Но они...
54652. Матеріали до філософсько-психологічного дослідження за романом П.Мирного «Хіба ревуть воли, як ясла повні?» 74.5 KB
  У ньому Панас Мирний відтворив свої враження і спостереження від подорожі а також історію яку він почув від візника про відомого на всю Полтавщину розбійника Гнидку засудженого на каторгу. Мирний був вражений тим що розповідаючи про злющого зарізяку візник здавалося співчував йому. Панас Мирний зацікавився особою Гнидки який у його пам’яті зостався як здоровенний іржавий цвях забитий у білу гладеньку стіну. Почуте у дорозі письменник намагався проаналізувати вдома проникнути в складність суспільного явища знайти коріння що...
54653. Конвенция о правах детей 108 KB
  Здравствуйте, дорогие мальчики и девочки! Посоветуйте, что же мне делать? Наверняка, вы читали сказку «Золушка» и знаете, как я люблю свою семью: отца, мачеху, сестёр своих. Но я сомневаюсь, любят ли они меня так, как я их. Как вы считаете? Почему я должна ночью. Когда мои сёстры спят, шить им бальные наряды? Почему моя мачеха основную работу по дому перекладывает на мои плечи? Разве это правильно?! Иногда мне очень хочется отдохнуть, но я не имею права отдохнуть, я должна всё успеть.
54654. Монополистическая конкуренция 31.16 KB
  Для монополистической конкуренции как рыночной структуры характерно относительно большое число небольших производителей. Эти производители предлагают похожую, но не идентичную продукцию. Дифференциация продукта может осуществляться в различных формах
54655. Защита от ионизирующих излучений 23 KB
  Защита от ионизирующих излучений Ионизирующее излучение – любое излучение взаимодействие которого со средой приводит к образованию в ней зарядов разных знаков т. К ионизирующим относятся: корпускулярные излучения состоящие из частиц с массой покоя отличной от нуля а αчастицы положительно заряженные – обладают высокой ионизирующей и низкой проникающей способностями; они ионизируют среду; б βчастицы отрицательно заряженные – поток электронов электрон – элементарная частица с наименьшим отрицательным электрическим...
54656. Общие сведения о процессе горения 44.5 KB
  Общие сведения о процессе горения Пожар – неконтролируемое горение вне специального очага наносящее ущерб вследствие уничтожения материальных ценностей. в источник зажигания – любое горючее вещество накаленное тело электрический разряд имеющие запас энергии и температуру достаточную для возникновения горения других веществ. Зажигание – воздействие источника зажигания на горючее вещество в присутствии кислорода приводящее к возникновению горения. Огонь – внешнее проявление горения сопровождающееся свечением в пламени.