OpenFrameworks: 2d-графика

Preview:

DESCRIPTION

Двумерная графика в OpenFrameworks, рисование фигур, изображения, прозрачность, экранный буфер. Creative Coding, Generative Art.

Citation preview

Разработка интерактивных систем на OpenFrameworks

Двумерная графика

УрГУ / ИММ весна 2011

лекции и объявления: www.uralvision.blogspot.com

вопросы по проектам и программированию: perevalovds@gmail.com

Настройка экрана

в main.cpp:

ofSetupOpenGL(&window, 1024,768, OF_WINDOW);

1024, 768 - размеры экрана, OF_WINDOW - вывод в окно.

Чтобы вывести на полный экран в 1280x1024:

ofSetupOpenGL(&window, 1280,768, OF_FULLSCREEN);

Настройка экрана

Переключение между полноэкранным режимом в ходе работы программы (в update()) :ofSetFullscreen(bool fullscreen) Пример: по нажатию '1'/'2' - вкл/выкл полноэкранный режим: void testApp::keyPressed(int key){ if ( key == '1' ) { ofSetFullscreen( true ); } if ( key == '2' ) { ofSetFullscreen( false ); }}

Настройка фона

ofBackground(int r, int g, int b) устанавливает цвет фона (по умолчанию 128, 128, 128).Примечание: надо ставить в setup(), если включен ofSetBackgroundAuto. ofSetBackgroundAuto(bool bAuto) - включает/выключает режим очистки картинки в каждом кадре, перед вызовом draw() (по умолчанию true).

Рисование фигурЛиния ofLine(float x1, float y1, float x2, float y2)

Прямоугольник ofRect(float x1, float y1, float w, float h)

Круг ofCircle(float x, float y, float radius)

Треугольник ofTriangle(float x1, float y1, float x2, float y2, float x3, float y3)

Эллипс ofEllipse

Многоугольник ofBeginShape(), ofVertex(), ofEndShape()

Гладкая кривая ofCurve

Рисование фигурНастройки: Цвет рисования ofSetColor(int red, int greeb, int blue), где числа от 0 до 255. ofSetColor(int red, int green, int blue, int alpha ) /*alpha - прозрачность, см. далее*/ ofSetColor(int hexColor) - 16-чная задание цвета, Толщина линий ofSetLineWidth(float lineWidth) толщина линий в пикселах

Заливать/не заливать фигуры ofFill() - заливать ofNoFill() - не заливать

Вывод текста- Простой вывод текста, без настроек шрифта и размера: ofDrawBitmapString("Some text", 50, 50 ); //параметры: текст и координаты - Для вывода нормальным шрифтом и размером - использовать ofTrueTypeFont:

1) скопировать в bin/data шрифт, например, verdana.ttf (есть в папке openframeworks) 2) объявить: ofTrueTypeFont myFont; 3) в setup(): myFont.loadFont("verdana.ttf", 32 /*размер*/); 4) в draw(): myFont.drawString("Good", 50, 50); - Вывод в текстовое окно консоли:cout << "Text" << endl;

Пример

Это то, что называется "генерируемое искусство" (generative art) и "творческое программирование" (creative coding)

Пример

Объявление переменных float px; //начало линии float py; float qx; //отступ float qy; float col; //цвет

setup() ofBackground( 255, 255, 255 ); ofSetBackgroundAuto( false ); px = 320; py = 240; qx = 0; qy = 0; col = 0;

Примерupdate() px += ofRandom( -1, 1 ); //ofRandom(a,b) - случайная велечина в [a,b] py += ofRandom( -1, 1 ); qx += ofRandom( -0.3, 0.3 ); qy += ofRandom( -0.3, 0.3 );

if ( px < 0 ) px += 640; if ( px >= 640 ) px -= 640; if ( py < 0 ) py += 480; if ( py >= 480 ) py -= 480;

if ( qx < -30 ) qx += 15; if ( qx > 30 ) qx -= 15; if ( qy < -30 ) qy += 15; if ( qy > 30 ) qy -= 15;

col += 0.02; if ( col >= 256 ) col = col - 256;

Примерdraw() int r = col; int g = int(col * 2) % 256; int b = 255 - col; ofSetColor( r, g, b ); ofLine( px, py, px + qx, py + qy );

Рисование изображений

КоллажКоллаж (от фр. collage — наклеивание) — технический приём в изобразительном искусстве, заключающийся в наклеивании на подложку предметов и материалов, отличающихся от основы по цвету и фактуре. Коллажем также называется произведение, целиком выполненное в этой технике. (Википедия) А здесь мы будем под коллажом понимать размещение различных картинок на экране.

Для коллажа нужно: - загрузить набор картинок,осуществить их - вращение, - перенос, - изменение размера,- прозрачность. http://www.chinesecontemporary.com/hong_hao_5.htm

Загрузка и рисование изображенияобъявление картинкиofImage image;

в setup()image.loadImage( "texture.jpg" ); //загрузка с диска //файл должен лежать в bin/data

в draw()ofSetColor( 255, 255, 255 ); //зачем это нужно - см. ниже //"Прозрачность всего изображения"image.draw ( 100.0, 50.0 ); //вывод на экран //левый верхний угол будет в (100, 50) Это изображение можно скачать с http://uralvision.blogspot.com/2010/03/4.htmlИсходное изображение было взято с http://ayesha5.files.wordpress.com/2008/06/sun-flower2.jpg

Поворот изображенияв draw() ofPushMatrix(); //запомнить матрицу преобразования ofRotate( 10.0 ); //поворот в градусах левого верх. угла image.draw( 0.0, 0.0 ); //рисуемofPopMatrix(); //восстановить матрицу

Вращение около своего центрав draw() //Рисуем повернутым, и чтоб центр был в ( 200.0, 100.0 ) ofPushMatrix(); ofTranslate( 200.0, 100.0 ); //центр картинки ofRotate( 20.0 ); //поворот //рисование со сдвигом: image.draw( -image.width / 2, -image.height / 2 ); ofPopMatrix();

Прозрачность

Прозрачность для пикселовЧтобы сделать хороший коллаж из нескольких картинок, нужно убрать черный фон. Это делается путем использования прозрачности для пикселов изображения.

Применение прозрачности для пикселов изображенияЕсли к каналам Red, Green, Blue добавить канал Alpha, то можно задавать прозрачность пикселов. Alpha = 0 - пиксел прозрачен и невидим,Alpha = 255 - пиксел полностью непрозрачен.То есть можно просто вырезать фон.

Схема смешивания цветов при прозрачностиОбычно данные о прозрачности хранятся в виде параметра "alpha". Это "непрозрачность". Если значение alpha фрагмента в [0, 1] (то есть alpha = Alpha / 255.0)то старый цвет C0 смешивается с цветом фрагмента C1 по формуле R = (1-alpha) * R0 + alpha * R1G = (1-alpha) * G0 + alpha * G1B = (1-alpha) * B0 + alpha * B1

Если alpha = 0 - новый цвет равен просто старому C0.Если alpha = 1 - новый цвет равен цвету фрагмента C1.При промежуточных значениях - происходит смешивание цветов.

Если несколько объектов накладываются - процедура выполняется последовательно, от дальнего к ближнему.

Схема смешивания цветов при прозрачностиКрасный квадрат накладываем на черный, белый и синий цвет.Накладываем три раза, с alpha: 0.3, 0.6, 1.0.

Способы получения изображений с вырезанным фоном 1. из векторного редактора 2. "умным" выделением краев в Photoshop или Gimp 3. вручную - плохое качество (алиасинг-рваные края)!

Форматы картинок, хранящие прозрачность1. Форматы, позволяющие хранить прозрачностьpng-24 - наилучший по качеству / размеру / скорости распаковкиbmp-32, tiff, tga.2. Форматы, которые хранят прозрачность 1-битовую (рваные края):gif, png-8.

3. Не хранит прозрачность в принципе: jpg.

Пример: вращающиеся подсолнухи

//Объявление переменных ofImage image; //картинкаfloat angle = 0.0; //угол вращения //Инициализация void testApp::setup(){ image.loadImage( "texture.png" ); //png - с прозрачностью angle = 0.0;}

//Обновление состоянияvoid testApp::update(){ angle += 0.1; //поворот}

Пример: вращающиеся подсолнухи//Рисованиеvoid testApp::draw(){ //включить режим прозрачности ofEnableAlphaBlending(); //2-й вариант, с точным указанием функции для прозрачности: //glEnable(GL_BLEND); //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

for (int i=0; i<5; i++) { ofPushMatrix(); ofTranslate( 300.0 + i * 100.0, 300.0 ); //перенос ofRotate( angle ); //вращение ofScale( 1.0 + 0.2 * i, 1.0 + 0.2 * i ); //увеличение размера image.draw( -image.width / 2, -image.height / 2 ); ofPopMatrix(); } ofDisableAlphaBlending(); //выключение режима прозрачности //glDisable(GL_BLEND);}

Прозрачность всего изображенияТакже для коллажей часто используют прозрачность для всего изображения (слоя). На картинке показан коллаж, где некоторые подсолнухи наложены с прозрачностью. А у двух подсолнухов к тому же сделана полная прозрачность (т.е. невидимы) соответственно Red, Blue и Green, Blue каналы.

Прозрачность всего изображения- это реализуется путем установки цвета ofSetColor( r, g, b, a), перед рисованием изображения.Дело в том, что изображения рисуются с попиксельным умножением на компоненты текущего цвета, что условно можно записать так: R = r / 255.0 *R0G = g / 255.0 *G0B = b / 255.0 * B0A = a / 255.0 * A0 Поэтому-то, чтобы вывести изображение без изменений, используется ofSetColor(255, 255, 255) перед рисованием изображения.

Внимание: если стоял черный цвет, то изображение будет невидимым. Это довольно часто встречающаяся "проблема"!

Прозрачность всего изображения//Рисованиеvoid testApp::draw(){ float w = image.width; float h = image.height; ofBackground(0, 0, 0); //задаем цвет фона ofEnableAlphaBlending(); //включение прозрачности

//текущий цвет влияет на выводимую текстуру //а именно, текстура поканально умножается на R,G,B компоненты //цвета и еще учитывается его прозрачность ofSetColor( 255, 255, 255 ); //непрозрачно image.draw( w, h );

ofSetColor( 255, 255, 255, 128 ); //полупрозрачно image.draw( w/2, h/2 );

ofSetColor( 0, 255, 0, 128 ); //полупрозрачно, только зеленый канал image.draw( w/2, h + h/2 ); ofDisableAlphaBlending(); //выключение прозрачности}

Результат

Рисование в буфер

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

Как это сделать? Если запоминать траекторию в виде ломаной и каждый раз ее выводить на экран - постепенно программа будет работать все медленней.Лучший способ решения - рисовать траекторию маятника в некоторый буфер вне экрана, а потом выдавать содержимое буфера на экран.

Этот буфер - как бы экран, который мы не видим. В отличие от экрана, буфер не будет чиститься при каждом рисовании экрана.

FBO - Frame Buffer Object

В такой буфер можно рисовать как на экране, а затем использовать результат как текстуру - т.е. выводить ее а экран или рисовать ей в других буферах.Можно делать сложные многослойные изображения, позволяющие делать эффекты типа "следа" от движущихся объектов. Для этого нужно рисовать один буфер в другом с разной прозрачностью.

Как нарисовать путь движения маятникаТогда алгоритм рисования в draw() будет такой: 1. в буфере рисуется прямая, соединяющая текущее положение маятника с предыдущим, 2. буфер выводится на экран3. на экране рисуется сам маятник

Работа с буфером рисования

Для работы с буфером рисования в OpenFrameworks лучше всего использовать аддон ofxFBOTexture.

Он состоит из двух файлов - ofxFBOTexture.h и ofxFBOTexture.cpp.http://addons.openframeworks.cc/projects/list_files/ofxfbotexture

Эти файлы нужно добавить в проект, например, так:1. Скопировать их в src проекта2. в VisualStudio ткнуть правой кнопкой по проекту, в меню - Add Existing Items и добавить их оба.

Правильней копировать все аддоны в папку openframeworks/addons, но это может быть неудобно, если проект должен быть мобильным, то есть собираться на разных компьютерах.

Работа с буфером рисования

... #include "ofxFBOTexture.h" ...ofxFBOTexture buffer; //буфер для рисования вне экрана

в setup() //создание буфера buffer.allocate( ofGetWidth(), ofGetHeight(), false //без автоочистки при каждом рисовании - т.к. будем там накапливать картинки );

buffer.clear( 0, 0, 0, 255 ); //очистка черным цветом

//нужно заметить, что если ставить не черный цвет, то буфер может окраситься в первый используемый вами цвет. Как устранить проблему?

Работа с буфером рисования

в draw() buffer.begin(); //начало рисования в буфер

// процедуры рисования в буфер - оформляется так же, как на экран ... ofSetColor, ofLine, ...

buffer.end(); //конец рисования в буфер buffer.draw( 0, 0 ); //вывод буфера на экран

// остальное рисование ...

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

Домашнее задание (*)

Нарисовать многоугольник, заполненный (текстурированный) некоторым изображением.

Подсказка. Схема вызова функций: ofTexture tex = image.getTextureReference();tex.bind();glBegin( GL_QUADS ); glTexCoord2f(...) glVertex2f(...) ...glEnd();tex.unbind();

Приложение:Запись видео работающей программы и публикация

Захват видео с экранаПрограмма CamStudio - бесплатная программа для захвата изображений с экрана и записи в видеофайл. http://camstudio.org При больших размерах захватываемой области скорость захвата может весьма низкой. Не забывайте при съемке вашего проекта установить режим Release, а не Debug.

Лучше использовать кодек CamStudio Lossless codec, он достаточно быстрый и не портит изображение. Но файлы получаются большого размера. Поэтому, перед публикацией, лучше конвертировать файл с помощью программы VirtualDub в другой кодек, например, XVID.

Публикация видеороликаГде публиковать: Youtube, Vimeo. Youtube - наиболее распространен, интегрирован во многие блоги; просматривается на устройствах iOS. Vimeo - качество видео превосходит Youtube, поэтому профессиональные работы публикуют часто одновременно и тут, и на Youtube.