Posts tagged "AIF"

Preview 3 and the future of PB3D

We have just released preview 3 of Pixel Bender 3D (PB3D) http://labs.adobe.com/technologies/pixelbender3d. This is the best preview to date in terms of reliability and stability. Please look at the release notes (http://labs.adobe.com/technologies/pixelbender3d/releasenotes.html) for the details.

PB3D remains an experiment, where we are exploring the utility of the language for high-level authoring of Stage 3D shaders. Workflows remain command-line based, and it is still easy to write programs that exceed the limitations of Stage 3D. To spend the resources to address the workflow issue would require a significant investment from Adobe, and to justify that we would need extraordinary uptake from the developer community. Please regard the current state of the system as an opportunity to evaluate whether the language is a useful design for your needs, and let us know if you would adopt it for main-line use given a more convenient workflow or language changes, or if it is useful in its current form. Unless PB3D gains significant momentum in the next few months, this is likely to be the last release.

Please note that this announcement only concerns Pixel Bender 3D. Pixel Bender 2D and Flash Player Stage 3D remain unchanged.

Prerelease 2 is now out

Prerelease 2 of the PixelBender3D API is now available on the Adobe labs site here:

http://labs.adobe.com/technologies/pixelbender3d/

There are a bunch of bug fixes, and some improvements to the public API to make it easier to set up input values. Check out the full release notes included with the prerelease.

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