Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Zebestov

Рейтинг: 5.00. Голосов: 3.

Создание Pixel Bender фильтра «Slide Wring». Введение

Запись от Zebestov размещена 12.06.2012 в 15:22
Обновил(-а) Zebestov 12.06.2012 в 15:25

Если кто помнит, в качестве "разведки боем" я смастерил в Pixel Bender довольно симпотный эффект смены изображений "Slide Wring". Сегодня я выставляю на ваш суд исходный код этого фильтра. Так я начну небольшой цикл уроков по созданию в программе Pixel Bender некоторых особенно интересных на мой взгляд эффектов.

Начинать знакомство с новым эффектом мы будем с самого интересного — с финального кода:
Код:
<languageVersion : 1.0;>
 
kernel SlideWring
<
    namespace : "Image Effects";
    vendor : "Vadim BELLinSKY";
    version : 3;
    description : "Slide Wring for Flash is an easy and effective method for flipping imapges.";
>
{
    parameter float2 size
    <
        minValue:       float2(0.0, 0.0);
        maxValue:       float2(2880.0, 2880.0);
        defaultValue:   float2(0.0, 0.0);
        description:    "Image size";
    >;
 
    parameter float borderThickness
    <
        minValue:       0.0;
        maxValue:       28.0;
        defaultValue:   7.0;
        description:    "Border thickness";
    >;
 
    parameter pixel3 borderColor
    <
        parameterType:  "colorRGB";
        minValue:       pixel3(0.00, 0.00, 0.00);
        maxValue:       pixel3(1.00, 1.00, 1.00);
        defaultValue:   pixel3(0.95, 0.95, 0.95);
        description:    "Border color";
    >;
 
    parameter float phase
    <
        minValue:       0.0;
        maxValue:       1.0;
        defaultValue:   0.0;
        description:    "Transition phase";
    >;
 
    input image4 src1;
    input image4 src2;
    output pixel4 dst;
 
    const float PI    = 3.1415926535;
    const float PI2   = PI * 2.0;
    const float PI_2  = PI * 0.5;
 
    const float shrinking = 0.1;
    const float shining = 0.75;
    const float shading = 0.75;
 
    #define width_2   float(size[0] * 0.5)
    #define height_2  float(size[1] * 0.5)
    #define period1   float(PI_2 / size[1])
    #define period2   float(PI / size[0])
 
    #define phase1    float((phase * 0.75 - 0.5) * PI2)
    #define phase2    float(shrinking * sin(phase * PI))
 
    void
    evaluatePixel()
    {
        float2 here = outCoord();
        bool borderFlag = false;
 
        float angleH = clamp(here.y * period1 - phase1, 0.0, PI);
        float cosH = cos(angleH);
        float cosHdiv = 1.0 / cosH;
 
        // calculating the value of the current pixel
        float angleV = here.x * period2;
        float sinV = sin(angleV);
        float dx = (width_2 - here.x) * cosHdiv;
        float dy = (height_2 - here.y) * (1.0 + phase2 * (1.0 + sinV));
        float absdx = abs(dx);
        float absdy = abs(dy);
 
        float thickness = borderThickness * cos(dy * period1 * 2.0) * sinV;
              thickness = thickness < 0.25 ? 0.0 : thickness;
 
        float2 here1 = here - float2(thickness, 0.0);
        float2 here2 = here + float2(thickness, 0.0);
 
        // calculating the value of a pixel on the left of the current one
        float dx1 = (width_2 - here1.x) * cosHdiv;
        float absdx1 = abs(dx1);
 
        // calculating the value of a pixel on the right of the current one
        float dx2 = (width_2 - here2.x) * cosHdiv;
        float absdx2 = abs(dx2);
 
        // helper conditions
        bool subcond1 = absdy < height_2;
        bool subcond2 = absdx1 < width_2;
        bool subcond3 = absdx2 < width_2;
        bool subcond4 = dx1 < -width_2;
        bool subcond5 = dx2 > -width_2;
        bool subcond6 = cosH < 0.0;
        // main conditions
        bool condition1 = ( (( subcond6 &&  subcond3) || (!subcond6 &&  subcond2)) && subcond1 );
        bool condition2 = ( ((!subcond6 && !subcond3) || ( subcond6 && !subcond2)) && subcond1 );
        bool condition3 = ( (( subcond4 &&  subcond5) || (!subcond4 && !subcond5)) && subcond1 );
        bool condition4 = absdx > width_2 || absdy > height_2;
 
        if (condition4)
        {
            // the pixel is outside the slide
            // but it still can be on the border
            if (condition1 || condition3)
            {
                borderFlag = true;
            }
            else
            {
                dst.a = 0.0;
            }
        }
        else
        {
            // the pixel is within the slide
            if (subcond6)
            {
                dst = sampleLinear(src1, float2(width_2 + dx, height_2 - dy));
            }
            else
            {
                dst = sampleLinear(src2, float2(width_2 - dx, height_2 - dy));
            }
            // but it still can be on the border
            if (condition2)
            {
                borderFlag = true;
            }
        }
 
        // shading/shining parameters
        float  shadingValue       = 1.0 - abs(cosH);
        float  shadingBorder      = shadingValue * shadingValue;
        float  shiningImage       = shadingBorder * shining;
        float  shadingImage       = shadingBorder * shading;
        pixel3 borderColorCorrect = borderColor * shadingBorder;
 
        if (subcond6)
        {
            // shining of the slide below the center
            dst.rgb += (1.0 - dst.rgb) * shiningImage;
        }
        else
        {
            // shading of the slide above the center
            dst.rgb *= 1.0 - shadingImage;
        }
 
        if (borderFlag)
        {
            // the pixel is somewhere on the border
            dst.a = 1.0;
 
            if ((dx <= width_2) && (abs(width_2 + dx2) <= 0.5 || abs(width_2 + dx1) <= 0.5))
            {
                // the pixel is located on the inner edge of the border
                dst.rgb = mix(borderColorCorrect, dst.rgb, 0.5);
            } else {
                // the pixel is somewhere inside the border
                dst.rgb = borderColorCorrect;
            }
 
            if ( (dx <= - width_2) && ( (abs(width_2 + dx2) <= 0.5) || (abs(width_2 + dx1) <= 0.5) ) )
            {
                // the pixel is located on the outer edge of the border
                dst *= 0.5;
            }
        }
        else
        {
            // edges smoothing
            float mh = clamp(height_2 + 0.5 - absdy, 0.0, 1.0);
            float mw = clamp(width_2  + 0.5 - absdx, 0.0, 1.0);
            float m  = mh * mw;
            dst *= m * m;
        }
    }
}
Этот «рулон обоев» появился не сразу. Сначала я пробовал просто скрутить изображение. Затем был добавлен второй слайд. Для пущего реализма необходимо было какое-то ребро, без него эффект выглядел плоско. Забегая вперед, скажу, что это будет самая занимательная часть. И в завершение, на скрученные листы пролился свет. Соблюдая ту же последовательность, мы подробно остановимся на каждом этапе.

Надо отметить, что уроки не будут раскрывать основ работы с Pixel Bender. Предполагается, что вы уже запустили программу, открыли пару примеров, познакомились с интерфейсом, почитали документацию и полны решимости создавать красивые эффекты, но еще не знаете как…

Готовьтесь. Скоро начинаем.

Взято тут.
Всего комментариев 3

Комментарии

Старый 12.06.2012 15:59 TanaTiX вне форума
TanaTiX
 
Аватар для TanaTiX
Спасибо за статьи, может и доберусь когда-нибудь до бендера.
Старый 15.06.2012 18:14 ~~~ вне форума
~~~
 
Аватар для ~~~
Молодец, круто! Как минимум потому, что знатоков мало и они нужны. А тем, кто в теме часто просто лень писать статьи. А ты крут, спасибо. Может теперь сам чего напишу, если здесь интерес народа будет.
Старый 17.06.2012 20:46 Zebestov вне форума
Zebestov
 
Аватар для Zebestov
Благодарю =)
 

 


Часовой пояс GMT +4, время: 03:55.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.