ЛЕКЦИЯ 7. Растровые объекты: изображения и текстуры
Вывод изображений в буфер OpenGL Изображение – это двумерный массив, в котором хранятся значения цветов отдельных пикселов. Существует большое количество форматов изображений, отличающихся способом представления цветовых значений (например, формат RGB, RGBA, BGR, палитровый формат) и расположением пикселов внутри массива (например, изображение может храниться в массиве в направлении сверху-вниз или снизу вверх). На дисках изображения записываются в различных графических файловых форматах (BMP, PCX, GIF, JPEG и др.), которые в основном отличаются способами упаковки повторяющихся цветовых значений для сокращения размера файла. В OpenGL есть функции для работы с изображениями, хранящимися в памяти в виде массива пикселей, но нет функций для чтения/записи графических файлов. Выполнять дисковые операции требуется с помощью других библиотек. В памяти OpenGL позволяет хранить изображения разными способами: значения цвета пикселей может храниться в виде RGB, BGR, RGBA и др. Рассмотрим один из наиболее часто используемых форматов – цвет пиксела хранится в формате RGB и занимает три байта (по байту на каждую из трех компонент). Строки хранятся в памяти последовательно, в порядке снизу-вверх. В библиотеке GLAUX есть функция для загрузки подобного изображения в память из BMP-файла: AUX_RGBImageRec* auxDIBImageLoadA(const char* filename); Эта функция возвращает указатель на структуру с динамически созданным изображением: struct AUX_RGBImageRec { int sizeX, sizeY; // Ширина и высота изображения unsigned char* data; // Пикселы изображения }; Для вывода изображения из памяти в буфер кадра в OpenGL предназначена функция glDrawPixels(): void glDrawPixels(int width, height, GLenum format, GLenum type, const void* pixels); Чтобы с помощью этой функции вывести изображение в буфер кадра, надо выполнить следующие действия:
1) загрузить изображение из файла в память; 2) указать способ хранения изображения в памяти и выравнивание; 3) установить точку начала вывода изображения (координату его левого нижнего угла) 4) вывести изображение в буфер. Рассмотрим выполнение этих действий на примере изображения SUNFLOWR.BMP, сохраненного в формате RGB, 24 бита на пиксел. Сначала в программе надо объявить глобальную переменную: AUX_RGBImageRec* pImage = NULL; Затем в функции main() перед входом в главный цикл auxMainLoop(display) надо внести строку: pImage = auxDIBImageLoad("sunflowr.bmp"); После выхода из главного цикла, перед завершением программы, надо добавить удаление динамически созданного изображения: delete pImage; Для вывода этого изображения в буфер кадра в функцию display() надо внести следующие строки: glRasterPos3d(-3, -2, 1); // Нижний левый угол изображения glPixelZoom(1, 1); // Коэффициенты масштабирования по // ширине и высоте glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // Способ хранения // изображения в памяти glDrawPixels(pImage->sizeX, pImage->sizeY, // Ширина и высота в пикселах GL_RGB, // Формат цвета пикселов GL_UNSIGNED_BYTE, // Формат цветовых компонент pImage->data); // Данные изображения При выводе в буфер изображения выводятся в масштабе, который задается функцией glPixelZoom(). Модельные преобразования на изображение не влияют, оно всегда выводится "параллельно плоскости экрана". Изображения удобно использовать в качестве статического фона. С помощью несложных преобразований можно сформировать изображение с прозрачными областями (см. упражнение 2).
Назначение текстур Для создания реалистичных трехмерных сцен возможностей вывода изображений недостаточно. Часто возникает потребность накладывать изображения на трехмерные объекты так, чтобы они оставались "наклеенными" на объекты при различных модельных преобразованиях. Для этих целей предназначены текстуры.
До сих пор геометрические примитивы рисовались либо каркасными, либо залитыми методом плоской или плавной заливки. Если попробовать нарисовать без использования текстур, например, большую кирпичную стену, то потребуется рисовать каждый кирпич в виде отдельного многоугольника. Плоская стена (которую удобно изобразить в виде одного параллелепипеда) может потребовать рисования тысяч отдельных кирпичей, причем кирпичи будут выглядеть слишком гладкими и правильно расположенными. Поэтому сцена будет выглядеть нереалистично. Отображение текстур позволяет "наклеить" изображение кирпичной стены (например, отсканированную фотографию настоящей стены) на многоугольник, а затем нарисовать всю стену как один многоугольник. Отображение текстур в OpenGL гарантирует, что все будет отображаться правильно при преобразованиях многоугольника. Например, в перспективной проекции, кирпичи будут уменьшаться в размерах по мере удаления от наблюдателя. Еще несколько примеров использования текстур – имитация растительности на больших многоугольниках, изображающих землю в авиасимуляторах; текстуры в виде обоев для построения интерьеров помещений, текстуры для имитации предметов из реальных материалов: мрамора, дерева, ткани и др. Хотя обычно текстуры применяются по отношению к многоугольникам, но их можно применять к любым примитивам, в том числе точкам и отрезкам. Текстуры – это обычные изображения, например, в формате RGBA. Отдельные точки текстуры иногда называются текселами (texels – элементы текстуры). Алгоритмы отображения текстур довольно сложны, т.к. требуется отображать прямоугольные текстуры на непрямоугольные области. Процесс отображения текстуры поясняется на рис. 7.1. Слева показана текстура целиком, на которой черным контуром отмечен четырехугольник, на который требуется отобразить данную область текстуры. При рисовании четырехугольника он может быть искажен в результате различных преобразований – поворотов, переносов, масштабирования и проецирования. Справа на рис. 7.1 показан текстурированный четырехугольник после нескольких преобразований (обратите внимание, что четырехугольник невыпуклый, поэтому его нельзя отобразить как один примитив OpenGL).
Рис. 7.1. Процесс наложения текстуры
OpenGL выполняет искажение текстуры в соответствии с преобразованиями четырехугольника. На рис. 7.1 текстура вытянута по оси x, сжата по оси y, немного повернута и сдвинута. В зависимости от размеров текстуры, искажения четырехугольника и размеров экранного изображения, некоторые из текселов могут отобразиться на участок из нескольких пикселов, или, наоборот, некоторые пикселы могут оказаться под несколькими текселами. Текстура состоит из дискретных текселов (например, 256×256), поэтому перед отображением на пикселы надо выполнить фильтрацию. Например, если на один пиксел попадает несколько текселов, их значения надо усреднить. Если границы тексела проходят по нескольким пикселам, то каждому такому пикселу надо присвоить взвешенное среднее от нескольких текселов. Вследствие подобных вычислений текстурирование требует больших вычислительных затрат, поэтому часто оно выполняется с помощью графических ускорителей.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|