Разработка интерактивных систем на OpenFrameworks Шейдеры УрГУ / ИММ весна 2011 лекции и объявления: www.uralvision.blogspot.com вопросы по проектам и программированию: [email protected]http://pixelnoizz.files.wordpress.com/2009/08/picture-54.png?w=510&h=259
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
1. Шейдерами сегодня обычно называют небольшие программы, которые графическая карта применяет для изменения геометрии объектов и пикселов изображений во время рендеринга.
2. Бывают вершинные (геометрия) и фрагментные (пиксельные) шейдеры.
3. Шейдеры выполняются на видеокарте и поэтому не загружают CPU. Поэтому с их помощью можно выполнять очень интересные и сложные трансформации и эффекты.
Что такое шейдеры
Шейдеры представляют собой небольшие программы на языке GLSL.
Их можно хранить в текстовых файлах. При старте вашего приложения они будут компилироваться и записываться в видеопамять.
Это удобно тем, что можно менять и настраивать шейдеры без перекомпиляции самого приложения.
Что требуется для использования шейдеров в OpenFrameworksВ этой лекции мы рассмотрим, как использовать фрагментные шейдеры для трансформации изображений в openFrameworks.
Необходимые компоненты:
1. Аддон ofxFBOTexture для рисования в буфер:ofxFBOTexture.h, ofxFBOTexture.cpp (см. "Рисование в буфер" в лекции по двумерной графике).
2. Аддон ofxShader для загрузки/выгрузки шейдеров:ofxShader.h, ofxShader.cpp
Их можно скачать, например, вhttp://playbat-common.googlecode.com/svn/trunk/of/
void main( void ) //эта функция будет применяться к каждому пикселу{ vec2 st = gl_TexCoord[0].st; //st - вектор входных координат пиксела vec4 color; //цвет, будем его накапливать for(float i = -4.0; i <= 4.0 ; i++) { float weight = 5.0 - abs(i); color += weight * texture2DRect(src_tex_unit0, st + vec2(blurAmount * i, 0)); //взятие цвета пиксела из текстуры src_tex_unit0, //с координатами x = st[0] + blurAmount * i, // y = st[1] } color /= 25.0; gl_FragColor = color; //установка выходному пикселу цвета color} ! Важно: компилятор автоматически не преобразует float <-> int, а выдает про это предупреждения и шейдер не запускается.
Текст шейдераСоздаем файл вершинного шейдера blur.vert в папке bin/data:
Это вершинный шейдер, который ничего не изменяет. Просто ofxShader для работы нужен и этот файл.
Текст приложения#include "ofxFBOTexture.h" //Рисование в буфер#include "ofxShader.h" //Шейдеры ofxFBOTexture buffer; //БуферofxShader shader; //ШейдерofVideoGrabber grabber; //Захват картинки с камеры
void testApp::setup() { ofBackground(255,255,255); grabber.initGrabber(640, 480); //запуск камеры buffer.allocate(640, 480, true); //true - автоочистка фоном на каждом шаге
//Загрузка шейдера из файлов blur.frag и blur.vert. //При старте, если будут ошибки в тексте шейдера, они выведутся на экран, //с номером строки с ошибкой. shader.loadShader("blur"); }
void testApp::update() { grabber.update(); //обновление картинки с камеры}
Текст приложенияvoid testApp::draw() { //Сначала заготавливаем картинку - рисуем ее в буфер buffer.begin(); ofSetColor(255, 255, 255); grabber.draw(0, 0); //В буфер выводим кадр с камеры buffer.end();
//Включаем шейдер shader.setShaderActive(true); //Устанавливаем параметр шейдера blurAmount float blurAmount = mouseX / 20.0; //mouseX - текущая координата мыши shader.setUniformVariable1f("blurAmount", blurAmount); //1f - то есть скаляр типа float //Рисуем, что требуется на экран, "пропуская" это через шейдер ofSetColor(255, 255, 255); buffer.draw(0, 0); //Выключаем шейдер shader.setShaderActive(false);}
Пример 2. Лупа
http://www.youtube.com/watch?v=H-mYdfaku90
Реализуем в точке мыши "лупу".
(Идея взята из примера shaderZoomExample http://forum.openframeworks.cc/index.php?topic=2729.0)
vec4 color = texture2DRect(src_tex_unit0, vec2(newX, newY) ); gl_FragColor = vec4( color[1], color[2], color[0], color[3] ); //перемешивание компонент цвета
Домашнее задание
1. ВихрьСделайте так, чтобы лупа внутри себя закручивала изображение.
Подсказка: поворачивать вектор в зависимости от значения dist/circleRadius.
2. Вода 1
В шейдерном языке есть функции sin, cos, atan.Сделайте волнообразное искажение изображения на экране, от центра экрана.Как будто уронили что-то в воду в центре экрана.Т.е. это должно быть видео, а не статичная картинка.
3. Вода 2С помощью нажатий мыши имитировать падение чего-то в воду на картинке.Реализовать это, к примеру, путем моделирования в текстуре амплитуду колебаний волн.