Posts tagged "PixelBender"

Displaying numbers in a kernel

One of the problems with Pixel Bender is that it’s always been difficult to debug. This kernel helps out a little – it provides a way to display integers and floats on screen.

The value you’re trying to display must be the same for each invocation of the kernel – that means that it can’t depend on outCoord in any way. If you’re trying to debug something that only happens at a particular position you’ll need to hard code that position in for testing.

There are two functions – one for displaying integers and one for displaying floats:

bool
displayInt( int n, int2 topLeft, int scale, int width, bool displayleadingZeros );

bool
displayFloat( float f, int2 topLeft, int scale, int width, int precision, bool displayleadingZeros );

Each of them returns a bool – if the return value is true the pixel is part of the number to be displayed and should be highlighted in some manner.

The kernel here exposes most of the options as parameters just to make it easy to play around with them – in practice just set them to reasonable constant values.

<languageVersion : 1.0;>
kernel NumberDisplay
<   
    namespace : "AIF Test";
    vendor : "Adobe";
    version : 1;
    description : "Display numbers";
>
{
    input image4 src;
    output pixel4 dst;

    parameter int intValue
    <
        minValue : -150;
        maxValue : 50;
        defaultValue: 10;
    >;

    parameter float floatValue
    <
        minValue : -15.0;
        maxValue : 15.0;
        defaultValue: 0.0;
    >;

    parameter bool displayleadingZerosParam
    <
        defaultValue: false;
    >;
        
    parameter int intScale
    <
        minValue : 3;
        maxValue : 10;
        defaultValue: 5;
    >;
    
    parameter int nDigitsParam
    <
        minValue : 5;
        maxValue : 10;
        defaultValue: 5;
    >;
    
    parameter int floatWidth
    <
        minValue : 10;
        maxValue : 20;
        defaultValue: 10;
    >;
    
    parameter int floatPrecision
    <
        minValue : 2;
        maxValue : 7;
        defaultValue: 2;
    >;
    
    parameter int floatScale
    <
        minValue : 3;
        maxValue : 10;
        defaultValue: 5;
    >;
    
    
    const int digitXSpacing = 4;

    bool
    hitPosition( float4x4 m, int2 p )
    {
        return m[ p[ 1 ] ][ p[ 0 ] ] > 0.5;
    }

    bool displayNegativeSign( int digit, int2 gridPosition )
    {
        bool result = false;

        if( gridPosition.x >= 0 && gridPosition.x < 3 && gridPosition.y >= 0 && gridPosition.y < 5 )
        {
                int offset1D = gridPosition.y * 3 + gridPosition.x;
                
                int2 matrixPosition = int2( int( mod( float( offset1D ), 4.0 ) ), offset1D / 4 );

                result = hitPosition( float4x4( 0, 0, 0,  0, 0, 0,  1, 1, 1,  0, 0, 0,  0, 0, 0,  0 ), matrixPosition );
        }

        return result;
    }
    
    bool displayDecimalPoint( int2 gridPosition )
    {
        bool result = false;

        if( gridPosition.x >= 0 && gridPosition.x < 3 && gridPosition.y >= 0 && gridPosition.y < 5 )
        {
                int offset1D = gridPosition.y * 3 + gridPosition.x;
                
                int2 matrixPosition = int2( int( mod( float( offset1D ), 4.0 ) ), offset1D / 4 );

                result = hitPosition( float4x4( 0, 0, 0,  0, 0, 0,  0, 0, 0,  0, 0, 0,  0, 1, 0,  0 ), matrixPosition );
        }

        return result;
    }
    
    bool displayInt( int n, int digit, int2 gridPosition, int width, bool displayleadingZeros )
    {
        bool result = false;

        for( int i = 0; i < width - ( digit + 1 ); ++i )
        {
            n /= 10;
        }

        if( n != 0 || digit == width - 1 || displayleadingZeros )
        {
            n = int( mod( float( n ), 10.0 ) );

            int offset1D = gridPosition.y * 3 + gridPosition.x;
            
            int2 matrixPosition = int2( int( mod( float( offset1D ), 4.0 ) ), offset1D / 4 );

            if( n == 0 ) result = hitPosition( float4x4( 1, 1, 1,  1, 0, 1,  1, 0, 1,  1, 0, 1,  1, 1, 1, 0 ), matrixPosition );
            if( n == 1 ) result = hitPosition( float4x4( 0, 0, 1,  0, 0, 1,  0, 0, 1,  0, 0, 1,  0, 0, 1, 0 ), matrixPosition );
            if( n == 2 ) result = hitPosition( float4x4( 1, 1, 1,  0, 0, 1,  1, 1, 1,  1, 0, 0,  1, 1, 1, 0 ), matrixPosition );
            if( n == 3 ) result = hitPosition( float4x4( 1, 1, 1,  0, 0, 1,  1, 1, 1,  0, 0, 1,  1, 1, 1, 0 ), matrixPosition );
            if( n == 4 ) result = hitPosition( float4x4( 1, 0, 1,  1, 0, 1,  1, 1, 1,  0, 0, 1,  0, 0, 1, 0 ), matrixPosition );
            if( n == 5 ) result = hitPosition( float4x4( 1, 1, 1,  1, 0, 0,  1, 1, 1,  0, 0, 1,  1, 1, 1, 0 ), matrixPosition );
            if( n == 6 ) result = hitPosition( float4x4( 1, 1, 1,  1, 0, 0,  1, 1, 1,  1, 0, 1,  1, 1, 1, 0 ), matrixPosition );
            if( n == 7 ) result = hitPosition( float4x4( 1, 1, 1,  0, 0, 1,  0, 0, 1,  0, 0, 1,  0, 0, 1, 0 ), matrixPosition );
            if( n == 8 ) result = hitPosition( float4x4( 1, 1, 1,  1, 0, 1,  1, 1, 1,  1, 0, 1,  1, 1, 1, 0 ), matrixPosition );
            if( n == 9 ) result = hitPosition( float4x4( 1, 1, 1,  1, 0, 1,  1, 1, 1,  0, 0, 1,  1, 1, 1, 0 ), matrixPosition );
        }            

        return result;
    }

    int getNDigits( int n )
    {
        return int( ceil( log2( float( n + 1 ) ) / log2( 10.0 ) ) );
    }

    void
    getGridInformation( int2 topLeft, int scale, out int digit, out int2 gridPosition )
    {
            float2 offsetFromTopLeftFloat = floor( outCoord() - float2( topLeft ) );
            int2 offsetFromTopLeftInt = int2( offsetFromTopLeftFloat );
            int2 gridOffsetFromTopLeftInt = int2( floor( float2( offsetFromTopLeftInt ) / float2( scale ) ) );

            digit = gridOffsetFromTopLeftInt.x / digitXSpacing;
            gridPosition = int2( gridOffsetFromTopLeftInt.x - digit * digitXSpacing, gridOffsetFromTopLeftInt.y );
    }

    // Returns true iff this is a position that might lead to a number being displayed
    bool 
    positionNeedsChecking( int digit, int2 gridPosition, int width )
    {
        return 
            gridPosition.x >= 0 && 
            gridPosition.x < 3 && 
            gridPosition.y >= 0 && gridPosition.y < 5 
            && digit >= 0 && digit < width;
    }

    bool
    displayInt( int n, int digit, int2 gridPosition, int scale, int width, bool displayleadingZeros )
    {
        bool result = false;
        
        bool negative = n < 0;
        n = n < 0 ? -n : n;

        int negativeDigitPosition = displayleadingZeros ? 0 : width - getNDigits( n ) - 1;

        if( negative && digit == negativeDigitPosition )
        {
            result = displayNegativeSign( digit, gridPosition );
        }
        else
        {
            result = displayInt( n, digit, gridPosition, width, displayleadingZeros );
        }

        return result;
    }
    
    bool
    displayInt( int n, int2 topLeft, int scale, int width, bool displayleadingZeros )
    {
        bool result = false;

        int digit;
        int2 gridPosition;

        getGridInformation( topLeft, scale, digit, gridPosition );

        if( positionNeedsChecking( digit, gridPosition, width ) )
        {
            result = displayInt( n, digit, gridPosition, scale, width, displayleadingZeros );
        }

        return result;
    }

    bool
    displayFloat( float f, int2 topLeft, int scale, int width, int precision, bool displayleadingZeros )
    {
        bool result = false;

        int i = int( f > 0.0 ? floor( f ) : ceil( f ) );
        float fra = f > 0.0 ? ( f - float( i ) ) : ( -f + float( i ) );

        int digit;
        int2 gridPosition;

        getGridInformation( topLeft, scale, digit, gridPosition );

        if( positionNeedsChecking( digit, gridPosition, width ) )
        {
            int intWidth = width - precision - 1;

            // Display the integer value
            if( positionNeedsChecking( digit, gridPosition, intWidth ) )
                result = displayInt( i, digit, gridPosition, scale, intWidth, displayleadingZeros );

            // Display the fractional value
            if( positionNeedsChecking( digit - intWidth - 1, gridPosition, precision ) )
                result = result || 
                   displayInt( int( fra * pow( 10.0, float( precision ) ) ) , digit - intWidth - 1, gridPosition, scale, precision, true );

            // Display the decinal point
            if( digit == intWidth )
            {
                result = result || displayDecimalPoint( gridPosition );
            }
        }
        
        return result;
    }

    void
    evaluatePixel()
    {
        dst = sampleNearest( src, outCoord() );

        if( displayInt( intValue, int2( 10, 10 ), intScale, 12, displayleadingZerosParam ) )
        {
            dst = float4( 1.0, 0.0, 0.0, 1.0 );
        }

        if( displayFloat( floatValue, int2( 10, 50 ), floatScale, floatWidth, floatPrecision, displayleadingZerosParam ) )
        {
            dst = float4( 0.0, 0.0, 1.0, 1.0 );
        }
    }
}

The AIF team is looking for a new engineering manager

The job posting for our new engineering manager is up on the Adobe job site. The AIF team develops the Pixel Bender language and all of the behind the scenes magic that makes it run so fast. Check it out here:

https://adobe.taleo.net/careersection/2/jobdetail.ftl?lang=en&job=08505

Pixel bender 3D public beta now available

We’re delighted to announce we’ve just released the first public beta for Pixel Bender 3D. The Pixel Bender 3D technology works in conjunction with the new Molehill Flash API to make it easy to write shaders for your 3D models. To find out more about PB3D and download the initial release go to http://www.adobe.com/go/pixelbender3d. To find out more about Molehill go to www.adobe.com/go/molehill.

Please bear in mind that this is a beta release – as you’ll see from the release notes there are plenty of bugs and missing features that we know about, and I am sure there are plenty that we don’t know about. We’ve set up a forum here that we’ll be monitoring – let us know what problems you find and what cool things you’re doing with PB3D.

Welcome!

Welcome to the new Pixel Bender blog. Over the past few years, Kevin Goldsmith has hosted Pixel Bender content on his Adobe blog, but finally Pixel Bender has a blog of its own.

Remember that there’s still lots of great Pixel Bender content on Kevin’s blog.