CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2002 ГОД

OpenGL и Delphi-2

Руслан РИЗВАНОВ rizvanov_ruslan@mail.ru

(Продолжение, начало см. в МК № 36, 40 (207, 211)).
В данной части сериала речь пойдет о поточечном выводе на экран и о том, что есть в библиотеке OpenGL для работы непосредственно с пикселами. Хотя эта библиотека известна именно по работе с трехмерной графикой, в ней есть много функций для плоскостных построений (2d), а также для работы с пикселами. И именно при создании двухмерной (плоской) графики точечный (попиксельный) вывод и все, что с ним связано, наиболее часто используется. Сюда относятся различные алгоритмы, с помощью которых генерируются эффекты — огня, линзы, звездного коридора, сглаживания изображения и т.д. Необходимость в непосредственной работе с пикселами может возникнуть и тогда, например, когда потребуется узнать цвет в определенной позиции области вывода (в некоторых случаях этим можно пользоваться для выбора объектов сцены). Короче говоря, знания в области 2d никому не повредят.

Теперь, после небольшого вступления, перейдем к практике. И, как всегда, сначала пример, а затем детальное описание работы с пикселами в OpenGL. Пример сегодня будет довольно занимательный. Он иллюстрирует одну из разновидностей эффекта морфинга — плавный переход одного изображения в другое. Существует довольно сложный морфинг, при котором происходит плавное изменение контуров одного изображения до получения другого, но мы рассмотрим более простой, основанный на смешении цветов. В этом случае результирующий цвет определяется по формуле C=C1+(C2-C1)*T/M, где С1 — цвет пиксела первого изображения; С2 — цвет пиксела второго изображения с теми же координатами, что и первого; M задает количество кадров морфинга; T — текущий кадр. Надеюсь, с этим все ясно. А теперь как это выглядит на практике. Создайте форму, разместите на ней кнопку и два изображения, каждое размером 50х50 точек (потом, конечно, можете в программе поменять размерности массивов и длину циклов, чтобы использовать другие картинки). Объявите глобальные переменные и константы и не забудьте объявить dc:HDC и hrc:HGLRC:

Затем в текст модуля добавьте процедуру, осуществляющую смешение цветов по формуле. Вот как она выглядит:

Теперь обработчик события OnClick кнопки приведите к следующему виду:

В обработчике события OnDestroy формы разместите текст, корректно завершающий работу приложения:

И, наконец, заключительный кусок кода — обработчик события OnCreate формы, имеющий следующий вид (текст процедуры SetDCpixelFormat я не привожу — вы можете взять его из примеров в предыдущих статьях):

Уже можно запустить и посмотреть, как пример работает. Понажимайте кнопку и увидите, как при каждом нажатии в результирующем изображении происходят изменения. Так как же все это работает?! Сначала, при создании формы, в обработчике события OnCreate формы в цикле заполняются массивы img и img1. Это делается таким образом: берется цвет изображения, стандартными командами getRvalue, getGvalue, getBvalue из полученного цвета извлекаются красная, зеленая и синяя составляющие, их значения заносятся в массивы img и img1. Обратите внимание на описание этих массивов — речь идет о трехмерных массивах. Первые два индекса можно считать размерами помещаемого в них изображения, третий может иметь три значения (0,1,2), определяющие ячейки массива, в которых хранятся составляющие цвета RGB (соответственно значениям третьего индекса). Если в составляющих цвета имеется alfa, то используется формат gl_rgba, тогда третий индекс может иметь значения 0,1,2,3 (Red, Green, Blue, Alfa). Это один из способов описания массивов изображений, используемых функциями считывания и вывода пикселов в OpenGL. После того как картинки считаны в массивы, по нажатию кнопки выполнятся следующие действия: командой glClear очистятся необходимые буферы (чтобы начисто рисовать новый кадр), затем командой glPixelStorei задастся выравнивание пикселов, используемое командами чтения/вывода для корректного чтения массива (или в массив) пикселов из памяти и вывода на экран (в данном случае используется байтовое выравнивание, т.к. массив байтов). Далее вызывается ранее описанная пользовательская процедура morph. Она, как уже говорилось, смешивает цвета двух изображений и результаты помещает в результирующий массив res. Уже знакомая вам команда glRasterPos, о которой говорилось в предыдущих статьях, устанавливает позицию вывода блока пикселов (координаты его левого нижнего угла). Наконец, glDrawPixels выводит собственно блок пикселов — результирующий массив res. В ее параметрах указывается ширина, высота блока, формат данных, хранимых в нем, их тип и указатель на этот блок (массив). Остается лишь отобразить содержимое буфера на форме и перерисовать ее.

В принципе, на этом можно было бы и закончить. Но так как, судя по письмам, эта тема интересна многим читателям, а не только мне, то не могу не удержаться от того, чтобы привести еще один занимательный пример и еще немного кое о чем порассказать :-).

Еще немного о пикселах

К сожалению, как бы красиво не выглядели все пиксельные эффекты, они очень медленны. Конечно, на тех компьютерах, что есть сегодня у большинства пользователей и геймеров, вывод относительно большого блока пикселов не особо сильно скажется на работе приложения. Но на компьютерах с процессорами ниже PII и со слабыми видеокартами может получиться глобальный слайд-шоу :-). А ведь такого рода компьютеров еще достаточно много, и их владельцам тоже хочется играть, хоть и в простые, но в 3D-игры. Лично мне в плане скоростных показателей нравится подход фирмы Sega — разнообразие настроек вывода 3D-графики (глубина цвета, разрешения и др.) позволяет более-менее нормально играть в их игры практически на любых компьютерах, чего не скажешь об играх некоторых других производителей. В общем, вам решать, насколько активно использовать прямую работу с пикселами в ваших программах, использовать ее вообще или, может, искать альтернативу. Например, во многих играх и демках отдано предпочтение текстурам. Ну да ладно — немного отвлекся от темы. Вернемся к командам OpenGL для работы с пикселами.

В рассмотренном выше примере описывалась только работа с выводом. Но ведь есть и функция для чтения блока пикселов —glReadPixels. Пример ее использования вы можете получить, слегка модифицировав предыдущий. Для этого обязательно установите параметры ClientWidth и ClientHeight формы, равными 220 и 180 соответственно. Почему — поймете позже. И поменяйте текст процедуры-обработчика события OnClick кнопки на следующий:

Добавьте в объявление переменных переменную fl типа byte — это будет флаг, разрешающий или запрещающий чтение пикселов. После этого допишите в модуль процедуру smooth (можно оставить процедуру morph, но она использоваться не будет):

Запустите и посмотрите, что происходит. На форме случайным образом выводятся линии, после этого считываются цвета пикселов в области вывода линий. Команда glReadPixels, осуществляющая считывание, очень схожа со стандартной низкоуровневой функцией getPixel, она тоже считывает цвета пикселов с контекста устройства (с формы). В параметрах glReadPixels указываются: координаты нижнего левого угла считываемого блока, размеры считываемого блока, формат считываемых значений, их тип и указатель на массив, куда будет произведено чтение. Обратите внимание на то, что команда glPixelStorei здесь не используется — чтение и вывод производятся с одинаковым выравниванием и поэтому в выводимом изображении нет никаких нежелательных смещений. Затем, когда пикселы считаны, вызывается наша процедура smooth. Она иллюстрирует еще один простой эффект —smooth (размытие). Этот эффект делается так: цвет пиксела в данной позиции определяется средним арифметическим, найденным от суммы составляющих цветов пикселов, расположенных выше, ниже, слева и справа от пиксела в данной позиции. Вообще, такой эффект делается также с помощью локальной фильтрации (матрицами). Это очень распространенный способ. Детально его описывать не буду. Если интересно, поищите в Интернете по фразе Image filtering. Далее в примере идут уже знакомые строки, описанные выше. Но в OpenGL есть еще одна интересная пиксельная команда —glPixelZoom. Она позволяет масштабировать выводимые блоки пикселов (в аргументах задаются масштабные коэффициенты — во сколько раз увеличить или уменьшить по x и по y). Попробуйте ее вставить перед выводом пикселов в этом и предыдущем примерах. Еще можно получить интересную картинку, если выводить массив с помощью glVertex (glBegin с аргументом gl_points). Например, есть массив 50х50. Запускается цикл вывода двумерного массива, в котором некоторые переменные i и k изменяются от 1 до 50. При выводе в аргументах glVertex указывается: glVertex2f (i/25, k/25). Устанавливая разные делители, можно получить эффектную разновидность масштабирования.

На этот раз все. Программируйте, экспериментируйте, рассматривайте приведенные здесь картинки, читайте МК, в общем, развлекайтесь по полной программе :-) и не пропустите следующую статью!

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov