Adjazent | Alan Ross


Getting started with Pixel Bender

I have been wanting to have a look at Pixel Bender for some time now. The Christmas holiday proved a perfect chance. Reading blog posts and looking at some examples by the usual suspects (Andrew Zupko, Joa Ebert, Mr.Doob, Tinic Uro, Pixelero, Lee Brimelow and Antti Kupila ), Adobes Pixel Bender Exchange and the ‘Pixel Bender Specification’ you can find under ‘Help’ in the Pixel Bender Toolkit menu was of great help.

Thought it would be fun applying the shader to a 3D model in Papervision, but it could be anything ( some shaders with their current settings also look good using input from a webcam… ).

The Collada cow I got from Papervision2.com, a fine place for Papervision related tutorials and examples.

Pixel Bender Shader Painting

You can view the Pixel Bender ‘Painting’ example in action here. The Pixel Bender code is as follows:

<languageVersion : 1.0;>

kernel Painting
<   namespace : "ar.shader.painting";
    vendor : "Alan Ross";
    version : 1;
    description : "Painting";
>
{
    parameter float n0
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.0;
    >;
    parameter float n1
    <
        minValue: 0.0;
        maxValue: 1.5;
        defaultValue: 0.6;
    >;
    parameter float n2
    <
        minValue: -0.5;
        maxValue: 0.5;
        defaultValue: 0.11;
    >;

    input image4 src;
    output pixel4 dst;

    void evaluatePixel()
    {
        float2 p = outCoord();
        float2 offset;
        float dist;
        float4 c, temp, p0, p1, p2, p3, p4, p5, p6, p7, p8;

        c = float4( n0, n0, n0, 1.0 );

        //-- no loops.

        dist = n1 * 1.0;
        offset.x = 0.0; offset.y = 0.0;
        p0 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y = -dist;
        p1 = sampleNearest( src, p + offset ); offset.x =  0.0;  offset.y = -dist;
        p2 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y = -dist;
        p3 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y =  0.0;
        p4 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y =  dist;
        p5 = sampleNearest( src, p + offset ); offset.x =  0.0;  offset.y =  dist;
        p6 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y =  dist;
        p7 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y =  0.0;
        p8 = sampleNearest( src, p + offset ); 

        if( any( lessThan( c, p0 ) ) ){ c = p0; }
        if( any( lessThan( c, p1 ) ) ){ c = p1; }
        if( any( lessThan( c, p2 ) ) ){ c = p2; }
        if( any( lessThan( c, p3 ) ) ){ c = p3; }
        if( any( lessThan( c, p4 ) ) ){ c = p4; }
        if( any( lessThan( c, p5 ) ) ){ c = p5; }
        if( any( lessThan( c, p6 ) ) ){ c = p6; }
        if( any( lessThan( c, p7 ) ) ){ c = p7; }
        if( any( lessThan( c, p8 ) ) ){ c = p8; }

        temp = ( p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 ) / 7.0;

        dist = n1 * 2.0;
        offset.x = 0.0; offset.y = 0.0;
        p0 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y = -dist;
        p1 = sampleNearest( src, p + offset ); offset.x =  0.0;  offset.y = -dist;
        p2 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y = -dist;
        p3 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y =  0.0;
        p4 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y =  dist;
        p5 = sampleNearest( src, p + offset ); offset.x =  0.0;  offset.y =  dist;
        p6 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y =  dist;
        p7 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y =  0.0;
        p8 = sampleNearest( src, p + offset );

        if( all( lessThan( c, temp ) ) ){ c.rgb += n2; }
        else { c.rgb -= n2; }

        if( any( lessThan( c, p0 ) ) ){ c = p0; }
        if( any( lessThan( c, p1 ) ) ){ c = p1; }
        if( any( lessThan( c, p2 ) ) ){ c = p2; }
        if( any( lessThan( c, p3 ) ) ){ c = p3; }
        if( any( lessThan( c, p4 ) ) ){ c = p4; }
        if( any( lessThan( c, p5 ) ) ){ c = p5; }
        if( any( lessThan( c, p6 ) ) ){ c = p6; }
        if( any( lessThan( c, p7 ) ) ){ c = p7; }
        if( any( lessThan( c, p8 ) ) ){ c = p8; }

        dist = n1 * 3.0;
        offset.x = 0.0; offset.y = 0.0;
        p0 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y = -dist;
        p1 = sampleNearest( src, p + offset ); offset.x =  0.0;  offset.y = -dist;
        p2 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y = -dist;
        p3 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y =  0.0;
        p4 = sampleNearest( src, p + offset ); offset.x =  dist; offset.y =  dist;
        p5 = sampleNearest( src, p + offset ); offset.x =  0.0;  offset.y =  dist;
        p6 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y =  dist;
        p7 = sampleNearest( src, p + offset ); offset.x = -dist; offset.y =  0.0;
        p8 = sampleNearest( src, p + offset );

        if( any( lessThan( c, p0 ) ) ){ c = p0; }
        if( any( lessThan( c, p1 ) ) ){ c = p1; }
        if( any( lessThan( c, p2 ) ) ){ c = p2; }
        if( any( lessThan( c, p3 ) ) ){ c = p3; }
        if( any( lessThan( c, p4 ) ) ){ c = p4; }
        if( any( lessThan( c, p5 ) ) ){ c = p5; }
        if( any( lessThan( c, p6 ) ) ){ c = p6; }
        if( any( lessThan( c, p7 ) ) ){ c = p7; }
        if( any( lessThan( c, p8 ) ) ){ c = p8; }

        dst = c;
    }
}

Pixel Bender Shader Drawing

This one I called ‘Drawing’, you can have a look at it here. the code is very simple and not optimized yet. Use the parameters to adjust the settings for input with other brightness:

<languageVersion : 1.0;>

kernel Drawing
<   namespace : "ar.shader.drawing";
    vendor : "Alan Ross";
    version : 1;
    description : "Drawing";
>
{
    parameter float n0
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.74;
    >;
    parameter float n1
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.45;
    >;
    parameter float n2
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.88;
    >;
    parameter float n3
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.90;
    >;
    parameter float n4
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.79;
    >;
    parameter float n5
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.75;
    >;
    parameter float n6
    <
        minValue: 0.0;
        maxValue: 1.0;
        defaultValue: 0.67;
    >;

    input image4 src;
    output pixel4 dst;

    void evaluatePixel()
    {
        float temp;
        float2 p = outCoord();
        float4 b = float4( 0.0, 0.0, 0.0, 1.0 );
        float4 w = float4( 1.0, 1.0, 1.0, 1.0 );

        float4 s = sampleNearest( src, p );

        float stroke0 = mod( p.x + p.y, 1.0 );
        float stroke1 = mod( p.x + p.y, 2.0 );
        float stroke2 = mod( p.x + p.y, 4.0 );
        float stroke3 = mod( p.x + p.y, 8.0 );
        float stroke4 = mod( p.x + p.y, 16.0 );
        float stroke5 = mod( p.x + p.y, 32.0 );

        float t6 = n6;
        float t5 = n5;
        float t4 = n4;
        float t3 = n3;
        float t2 = n2;
        float t1 = n1;
        float t0 = n0;

        float4 c = w;

        temp = ( s.r + s.g + s.b ) / 3.0;
        s.r = temp;
        s.g = temp;
        s.b = temp;

        if( s.r < t0 && stroke0 <= 1.0 ){ c = b; }
        if( s.r < t1 && stroke1 <= 1.0 ){ c = b; }
        if( s.r < t2 && stroke2 <= 1.0 ){ c = b; }
        if( s.r < t3 && stroke3 <= 1.0 ){ c = b; }
        if( s.r < t4 && s.r > t5 && stroke1 <= 1.0 ){ c = b; }
        if( s.r < t5 && stroke2 <= 1.0 ){ c = b; }
        if( s.r < t6 && stroke3 <= 1.0 ){ c = b; }

        dst = c;
    }
}

Pixel Bender Shader Ink

Here is one that looks a little like ‘Ink Outlines’.

<languageVersion : 1.0;>

kernel Ink
<   namespace : "ar.shader.ink";
    vendor : "Alan Ross";
    version : 1;
    description : "Ink";
>
{
    parameter float n0
    <
        minValue: 0.0;
        maxValue: 0.5;
        defaultValue: 0.25;
    >;
    parameter float n1
    <
        minValue: 0.2;
        maxValue: 1.0;
        defaultValue: 0.20;
    >;
    parameter float n2
     <
      minValue: 0.0;
      maxValue: 1.0;
      defaultValue: 0.20;
     >;

    input image4 src;
    output pixel4 dst;

    void evaluatePixel()
    {
        float2 pos = outCoord();
        float2 offset;
        float dist;
        float4 c, m, p0, p1, p2, p3, p4, p5, p6, p7, p8;

        c = float4( n0, n0, n0, 1.0 );

        dist = n1 * 1.0;
        offset.x = 0.0; offset.y = 0.0;
        p0 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y = -dist;
        p1 = sampleNearest( src, pos + offset ); offset.x =  0.0;  offset.y = -dist;
        p2 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y = -dist;
        p3 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y =  0.0;
        p4 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y =  dist;
        p5 = sampleNearest( src, pos + offset ); offset.x =  0.0;  offset.y =  dist;
        p6 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y =  dist;
        p7 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y =  0.0;
        p8 = sampleNearest( src, pos + offset ); 

        m = (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 ) / 7.0;

        if( any( lessThan( c, p0 ) ) ){ c = p0; }
        if( any( lessThan( c, p1 ) ) ){ c = p1; }
        if( any( lessThan( c, p2 ) ) ){ c = p2; }
        if( any( lessThan( c, p3 ) ) ){ c = p3; }
        if( any( lessThan( c, p4 ) ) ){ c = p4; }
        if( any( lessThan( c, p5 ) ) ){ c = p5; }
        if( any( lessThan( c, p6 ) ) ){ c = p6; }
        if( any( lessThan( c, p7 ) ) ){ c = p7; }
        if( any( lessThan( c, p8 ) ) ){ c = p8; }

        dist = n1 * 2.0;
        offset.x = 0.0; offset.y = 0.0;
        p0 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y = -dist;
        p1 = sampleNearest( src, pos + offset ); offset.x =  0.0;  offset.y = -dist;
        p2 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y = -dist;
        p3 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y =  0.0;
        p4 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y =  dist;
        p5 = sampleNearest( src, pos + offset ); offset.x =  0.0;  offset.y =  dist;
        p6 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y =  dist;
        p7 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y =  0.0;
        p8 = sampleNearest( src, pos + offset );

        if( any( lessThan( c, p0 ) ) ){ c = p0; }
        if( any( lessThan( c, p1 ) ) ){ c = p1; }
        if( any( lessThan( c, p2 ) ) ){ c = p2; }
        if( any( lessThan( c, p3 ) ) ){ c = p3; }
        if( any( lessThan( c, p4 ) ) ){ c = p4; }
        if( any( lessThan( c, p5 ) ) ){ c = p5; }
        if( any( lessThan( c, p6 ) ) ){ c = p6; }
        if( any( lessThan( c, p7 ) ) ){ c = p7; }
        if( any( lessThan( c, p8 ) ) ){ c = p8; }

        dist = n1 * 3.0;
        offset.x = 0.0; offset.y = 0.0;
        p0 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y = -dist;
        p1 = sampleNearest( src, pos + offset ); offset.x =  0.0;  offset.y = -dist;
        p2 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y = -dist;
        p3 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y =  0.0;
        p4 = sampleNearest( src, pos + offset ); offset.x =  dist; offset.y =  dist;
        p5 = sampleNearest( src, pos + offset ); offset.x =  0.0;  offset.y =  dist;
        p6 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y =  dist;
        p7 = sampleNearest( src, pos + offset ); offset.x = -dist; offset.y =  0.0;
        p8 = sampleNearest( src, pos + offset );

        if( any( lessThan( c, p0 ) ) ){ c = p0; }
        if( any( lessThan( c, p1 ) ) ){ c = p1; }
        if( any( lessThan( c, p2 ) ) ){ c = p2; }
        if( any( lessThan( c, p3 ) ) ){ c = p3; }
        if( any( lessThan( c, p4 ) ) ){ c = p4; }
        if( any( lessThan( c, p5 ) ) ){ c = p5; }
        if( any( lessThan( c, p6 ) ) ){ c = p6; }
        if( any( lessThan( c, p7 ) ) ){ c = p7; }
        if( any( lessThan( c, p8 ) ) ){ c = p8; }

        if( all( lessThan( c, m ) ) ){ c.rgb += n2; }
        else { c.rgb -= n2; }

        dst = c;
    }
}

Hope this is a useful starting point for anyone.

2 Comments. Leave a comment too

Drew Shefman
May 26, 2009

This is great. It works perfect in Pixel Bender toolkit. But when I apply it within flex to a transparent png, the background goes all black. I’m not getting that effect in Pixel Bender though.

Do you have any ideas?


Popular

Subscribe

Meta