📜 ⬆️ ⬇️

Pixel Bender. Language specification in the context of programming with Flash Player

Pixel bender This article is a free translation of the official Pixel Bender language documentation from Adobe. I want to immediately note that this translation is exactly the Pixel Bender Language Reference, and not the Pixel Bender Developer's Guide. As Google suggests, this topic has not yet emerged on the RuNet, and therefore I would like to correct such an annoying omission)) The translation has deliberately omitted programming questions for Adobe Photoshop and Adobe AfterEffects, since I was only interested in writing filters for Flash Player.

Pixel Bender is a high-performance graphic programming technology for image processing.
Pixel Bender kernel is a C-like language with image processing extensions. It is based on GLSL, which, in turn, is based on C. The basics of the language syntax should be familiar to any C programmer.
The main unit of image processing in Pixel Bender is the kernel ( kernel ). ( Note: I do not know how to translate this word more precisely, so I trusted Google;)). Each program on the Pixel Bender defines one core. The kernel is an object that contains the result of processing a single pixel by a function with an arbitrary number of arguments that can be obtained from one or more source images.


Using filters written in Pixel Bender



Adobe provides Pixel Bender Toolkit IDE - an integrated development environment for writing programs in the Pixel Bender language. Working with Pixel Bender Toolkit IDE is described in Pixel Bender Developer's Guide ( Note. Trans.: IDE free. You can get the Windows version from here ).
During development, you can run programs in Pixel Bender Toolkit IDE, which provides a convenient interface for this. For information on the Pixel Bender Toolkit IDE, see the Pixel Bender Developer's Guide.
To run filters in Flash Player, you must save your files with the .pbj extension.
The client application can, in its own way, organize access to the parameters for starting and operating the filter:

')

Preprocessor directives



The following preprocessor directives are available for use (similar to the C preprocessor directives):

#if
#ifdef
#defined
#endif
#elif
#define

Since Flash Player works on a wide range of equipment, only part of the Pixel Bender language is available for use in Flash Player. The following is a list of restrictions that Flash Player imposes on using the Pixel Bender language:



Kernel syntax



In each program written on Pixel Bender, there is one code block containing a set of metadata enclosed in angle brackets, and another code block describing the core, the set of variables, and the operations performed, enclosed in braces.

<languageVersion : 1.0;>
kernel name
<
kernel metadata pairs
>
{
kernel members
}


Each kernel must begin with the version of the language in which the code is written.
The first part of the kernel defines a metadata block consisting of a group of name-value pairs enclosed in angle brackets:

<
name1 : value1;
name2 : value2;
...
>;


The following metadata values ​​are predefined:

namespace - Required. The namespace in which the kernel is defined.
vendor - Required. Publisher.
version - Required. Integer, version number of the implementation of this kernel. This is not the same as languageVersion (!).
description - Optional. Description of the filter.

For example:

<
namespace : "Pixel Bender IDE";
vendor : "Adobe";
version : 1;
description: "A sample filter";
>


The second part of the kernel definition is a set of variables and functions enclosed in braces. The kernel must contain at least the definition of the evaluatePixel () function, and everything else is optional.

{
[declarations]
[support functions]
void evaluatePixel()
{
statements
}
}


Variable declarations usually contain a pixel declaration of the input and output image. Parameters and constants that will be used in functions can also be included.
The main function, evaluatePixel () , is used to enter images or images on which the conversion is performed, the result of which is one pixel.
Before the definition of the evaluatePixel () function can be (optionally) described:

  1. Options:

    parameter type name
    <
    name1 : value1;
    name2 : value2;
    ...
    >


    Parameters are set to read only, within the kernel function. Parameters can be of any (available for use within the Flash Player) type, except for images.
  2. Constants:

    const type name=compile-time_expression;

    The values ​​of the constants are determined at compile time.
  3. input:

    input type name;

    The image used as an argument to the evaluatePixel () function. Its type must be image1, image2, image3, or image4.
  4. output:

    output type name;

    A set of pixels resulting from the function evaluatePixel () . Its type must be pixel1, pixel2, pixel3, or pixel4.



Metadata Settings



Parameters may include data that describe this parameter or impose restrictions on its use. This data will be available within client applications after compilation, and will also help the programmer decide how to design a user interface that allows users to set the value of a parameter.
Data values ​​are enclosed in angle brackets following the parameter declaration.

parameter type name
<
name1 : value1;
name2 : value2;
...
>


Names are strings. Values ​​are constants of any valid Pixel Bender type. For int, float and bool types, the type definition is automatic. For other types, it is not necessary to define a constant value of a valid type (for example: float2 (1.0, -1.0)) or a string delimited by double quotes. For example:

parameter int angle
<
minValue : 0;
maxValue : 360;
defaultValue : 30;
description : "measured in degrees";
>;


This parameter imposes restrictions on possible values:

minValue - the minimum value allowed
maxValue - the maximum allowed value
defaultValue is the default
description - a description of the parameter that can be used as a hint in the client application.

Kernel function definition



The kernel function definition must meet these conditions:

Everything except evaluatePixel () is optional.

Function syntax:

void evaluatePixel()
{
statements
}


Types of data language Pixel Bender



Pixel Bender is a strongly typed language. There are no automatic type conversions, with one exception: between floating-point vector data types and matrix data types. There are several types of data, each of which is defined within a specific set of operators and eigenfunctions.

Pixel Bender supports the following basic data types:

bool - a logical data type
int is an integer
float is a floating point number
pixel1 - determines the value of one image channel. The number “1” distinguishes this type of data from similar ones, but determining the values ​​of several image channels. A time type of this type is represented by a floating point number and occupies 32 bits of memory.

All of these data types can participate in numeric operations.

Conversions between scalar data types



The bool, int, and float data types can be converted from one to another using the usual rules in the C-style:

type (expression)

For example:

int a = int(myfloat)

The pixel1 data type can be interchangeable with the float data type.

Note:

The int data type occupies 16 bits of memory (without a sign), but its implementation can take more than 16 bits of memory. You can perform conversions between int and float types. When the conversion result from the int type to the float type cannot be represented as the int type, the value of the variable becomes undefined.

Vector data types



Pixel Bender supports 2, 3, and 4-element counterparts for each scalar data type:

float2 bool2 int2 pixel2
float3 bool3 int3 pixel3
float4 bool4 int4 pixel4

Initialization of any type (including pixel) is represented by a general form:

vectorType (element1 [, element2 ...])

For example:

float3(0.5, 0.6, 0.7)

There is also an abbreviated version of the record (the following expressions are equivalent):

float3(0.3);
float3(0.3, 0.3, 0.3);


You can access the value of a vector variable by index or name by the following rules:

  1. Using the index operator, as an array element:

    vectorValue [index]

  2. Using dot notation to access elements in this sequence:

    r, g, b, a
    x, y, z, w
    s, t, p, q

    Each of these elements corresponds to an index from 0 to 3.


For example, to get the value of the first element of the vector myVectorValue, you can use any of the following record options:

myVectorValue [0]
myVectorValue.r
myVectorValue.x
myVectorValue.s

Select and override element values



Pixel Bender supports swizzling to select and redefine the order of the elements of a vector. For a vector with an n-number of elements, the values ​​can be followed by the point operator. The corresponding values ​​of the elements of the vector form a new result with as many elements as the assigned variable. This syntax can be used to change the order, to delete or repeat elements of the vector. For example:

float4 vec4;
float3 no_alpha = vec4.rgb; // vec4
float3 no_r = vec4.gba; // vec4
float4 reversed = vec4.abgr; //
float4 all_red = vec4.rrrr; //
float4 all_x = vec4.xxxx; //


Pointers from individual sequences cannot be combined:

float4 vec4;
float3 no_alpha = vec4.rgz; // !


Index pointers can also be used on the left side of an assignment expression. In this case, the indexes can not be repeated. This feature is used to write masking ( Appro. Ln .: in the original - write masking). The right side of the assignment expression must have the correct number of arguments:

float3 vec3;
float2 vec2;
vec3.xy = vec2; // sets the values ​​of vec2 vector elements to vec3 vector elements with indices 0 and 1
vec3.xz = vec2; // sets the values ​​of vec2 vector elements to vec3 vector elements with indices 0 and 2

Interaction:

Swizzling and masking can be used simultaneously on both sides of an assignment expression:

vec3.xz = vec4.wy;

There is the likelihood of complications between swizzling and assignment operations. Consider the following example:

g.yz *= g.yy;

A simplified version of this record can be represented as follows:

gy *= gy;
gz *= gy;


The problem is that the gy value in the second line has been changed. The correct solution would be the following entry:

float2 temp = g.yz * g.yy;
g.yz = temp;


Conversions between vector data types



Conversions between vector data types are permissible, provided that the sizes of the assignment operands are equal. The conversion itself is similar to the conversion between scalar data types:

type (expression)

For example:

float3 fvec3;
int3 ivec3;
fvec3 = float3(ivec3);


Matrix Types



There are the following types of matrices:

float2x2
float3x3
float4x4

Creating matrices using a constructor implies using float vectors to specify the values ​​of matrices, or specifying the values ​​of scalar variables of type float for each element of the matrix in the order column-row or a mixture of vectors and scalar variables of type float:

float2x2 (float2, float2)

float2x2 (float, float,
float

float3x3 (float3, float3, float3)

float3x3 (float, float, float,
float, float, float,
float, float, float)

float4x4 (float4, float4, float4, float4)

float4x4 (float, float, float, float,
float, float, float,
float, float, float,
float, float, float, float)

You can also initialize the matrix with one scalar variable of type float, which will determine the values ​​of the matrix elements on the main diagonal. All other values ​​will be set to zero:

float2x2 (float)
float3x3 (float)
float4x4 (float)

To access the values ​​of matrix elements, use the following syntax:

matrix [column] [row]

If you omit the indication of the series, then the whole column is selected and the vector variable of the appropriate dimension is returned:

matrix [column]

Other data types



Types of image data.

Pixel Bender also supports image variables. They are represented by the following data types:

image1
image2
image3
image4

Variables of these types cannot be created or used in expressions. However, they can be passed as arguments to the built-in functions of the language.

The data type is void.

Functions that do not return values ​​must be defined with the void type.

Operators



Pixel Bender defines the following types of operators for arithmetic operations on scalar data types. Here they are listed in order of priority. The brackets can be used to change this order:

. Variable element selection
++ - Postfix increment and decrement operators
++ - Prefix increment and decrement operators
-! Unary negation operator, logical "NOT"
* / Multiplication, division
+ - Addition, subtraction
<> <=> = Comparisons
==! = Equality
&& Logical "And"
^^ Logical "EXCLUSIVE OR"
|| Logical "OR"
= + = - = * = / = Operator grouping
?: A brief record of branch operators. This operator can only be used to select between two variables or constants (on the right side), but not expressions.

Operations on data types with several elements



Standard arithmetic operators (+, -, *, /) can be used for operations on scalar and vector and matrix data types. A binary operator can be applied to two vector operands only if they have the same size. In this case, the operation is performed for each element of the vector. For example:

float3 x, y, z;
z = x + y;

This entry is equivalent to the following:

z [0] = x [0] + y [0];
z [1] = x [1] + y [1];
z [2] = x [2] + y [2];

The grouping of scalar and vector pairs is also admissible. For example:

float3 x, y;
float w;
x = y * w;

This entry is equivalent to the following:

x [0] = y [0] * w;
x [1] = y [1] * w;
x [2] = y [2] * w;

An important exception to this rule is the multiplication of matrices between themselves and matrices with vector variables. Multiplication is carried out according to the rules of a linear algerb (and not componentwise):

float2x2 * float2x2 Multiply matrices according to the rules of linear algebra
float3x3 * float3x3
float4x4 * float4x4

float2x2 * float2 Column multiplication by vector
float3x3 * float3
float4x4 * float4

float2 * float2x2 Multiply rows by vector
float3 * float3x3
float4 * float4x4

Built-in language features Pixel Bender



Mathematical functions:

Like arithmetic operators, mathematical functions can be performed on vector data types. In this case, they work component by component. Unless otherwise specified, all angles are in radians.

float radians (float degrees) Converting degrees to radians
float2 radians (float2 degrees)
float3 radians (float3 degrees)
float4 radians (float4 degrees)

float degrees (float radians) Convert radians to degrees
float2 degrees (float2 radians)
float3 degrees (float3 radians)
float4 degrees (float4 radians)

float sin (float radians) Returns the sine of the argument
float2 sin (float2 radians)
float3 sin (float3 radians)
float4 sin (float4 radians)

float cos (float radians) Returns the cosine of the argument
float2 cos (float2 radians)
float3 cos (float3 radians)
float4 cos (float4 radians)

float tan (float radians) Returns the tangent of the argument. If x == pi / 2.0 returns undefined
float2 tan (float2 radians)
float3 tan (float3 radians)
float4 tan (float4 radians)

float asin (float x) Returns the arcsine of the argument. The return value is in the range [-pi / 2..pi / 2]
float2 asin (float2 x)
float3 asin (float3 x)
float4 asin (float4 x)

float acos (float x) Returns the arc cosine of the argument. The return value is in the range [0..pi]
float2 acos (float2 x)
float3 acos (float3 x)
float4 acos (float4 x)

float atan (float y_over_x) Returns the arctangent of the argument. The return value is in the range [-pi / 2..pi / 2]
float2 atan (float2 y_over_x)
float3 atan (float3 y_over_x)
float4 atan (float4 y_over_x)

float atan (float y, float x) Returns the arctangent of the expression y / x. The return value is in the range [-pi..pi]
float2 atan (float2 y, float2 x)
float3 atan (float3 y, float3 x)
float4 atan (float4 y, float4 x)

float pow (float x, float y) Returns x to the power of y and undefined if x <0
float2 pow (float2 x, float2 y)
float3 pow (float3 x, float3 y)
float4 pow (float4 x, float4 y)

float exp (float x) Returns e to the power x ( Approx. ln .: I don’t remember what this value is called :))
float2 exp (float2 x)
float3 exp (float3 x)
float4 exp (float4 x)

float exp2 (float x) Returns 2 to the power x
float2 exp2 (float2 x)
float3 exp2 (float3 x)
float4 exp2 (float4 x)

float log (float x) Returns the natural logarithm of x
float2 log (float2 x)
float3 log (float3 x)
float4 log (float4 x)

float log2 (float x) Returns the natural logarithm of x with base 2
float2 log2 (float2 x)
float3 log2 (float3 x)
float4 log2 (float4 x)

float sqrt (float x) Returns the positive square root of x and undefined if x <0
float2 sqrt (float2 x)
float3 sqrt (float3 x)
float4 sqrt (float4 x)

float inverseSqrt (float x) Returns the inverse of the positive square root of x and undefined if x <0
float2 inverseSqrt (float2 x)
float3 inverseSqrt (float3 x)
float4 inverseSqrt (float4 x)

float abs (float x) If x> = 0, returns x, otherwise returns -x
float2 abs (float2 x)
float3 abs (float3 x)
float4 abs (float4 x)

float sign (float x) If x <0, returns -1
float2 sign (float2 x) If x == 0, returns 0
float3 sign (float3 x) If x> 0, returns 1
float4 sign (float4 x)

float floor (float x) Rounds x down (returns an integer)
float2 floor (float2 x)
float3 floor (float3 x)
float4 floor (float4 x)

float ceil (float x) Rounds x up (returns an integer)
float2 ceil (float2 x)
float3 ceil (float3 x)
float4 ceil (float4 x)

float fract (float x) Returns x - floor (x)
float2 fract (float2 x)
float3 fract (float3 x)
float4 fract (float4 x)

float mod (float x, float y) Returns x - y * floor (x / y)
float2 mod (float2 x, float2 y)
float3 mod (float3 x, float3 y)
float4 mod (float4 x, float4 y)

float min (float x, float y) If x <y returns x, otherwise returns y
float2 min (float2 x, float2 y)
float3 min (float3 x, float3 y)
float4 min (float4 x, float4 y)

float max (float x, float y) If x> y, returns x, otherwise returns y
float2 max (float2 x, float2 y)
float3 max (float3 x, float3 y)
float4 max (float4 x, float4 y)

float step (float x, float y) If y <x, returns 0.0, otherwise returns 1.0
float2 step (float2 x, float2 y)
float3 step (float3 x, float3 y)
float4 step (float4 x, float4 y)

float clamp (float x, float minval, float maxval) If x <minval, returns minval. If x> maxval, returns maxval. Otherwise, it returns x.
float2 clamp (float2 x, float2 minval, float2 maxval)
float3 clamp (float3 x, float3 minval, float3 maxval)
float4 clamp (float4 x, float4 minval, float4 maxval)

float mix (float x, float y, float a) Returns x * (1.0 - a) + y * a (this is a linear interpolation between x and y).
float2 mix (float2 x, float2 y, float2 a)
float3 mix (float3 x, float3 y, float3 a)
float4 mix (float4 x, float4 y, float4 a)

float smoothStep (float edge0, float edge1, float x) If x <= edge0, returns 0. If x> = edge1, returns 1, otherwise smoothed interpolation is performed ( Note: original: smooth hermite interpolation).
float2 smoothStep (float2 edge0, float2 edge1, float2 x)
float3 smoothStep (float3 edge0, float3 edge1, float3 x)
float4 smoothStep (float4 edge0, float4 edge1, float4 x)

Geometric functions:

These functions work with vectors as with an integer object, and do not consider each element of the vector as separate.

float length (float x) Returns the length of the vector x
float length (float2 x)
float length (float3 x)
float length (float4 x)

float distance (float x, float y) Returns the distance between x and y
float distance (float2 x, float2 y)
float distance (float3 x, float3 y)
float distance (float4 x, float4 y)

float dot (float x, float y) Returns the scalar product x and y
float dot (float2 x, float2 y)
float dot (float3 x, float3 y)
float dot (float4 x, float4 y)

float3 cross (vector3 x, vector3 y) Returns the vector product x by y

float normalize (float x) Returns a vector with the same direction as x, but with a length of 1 and undefined if length (x) == 0
float2 normalize (float2 x)
float3 normalize (float3 x)
float4 normalize (float4 x)

These functions are performed by component multiplication (in contrast to the operator *, which performs algebraic multiplication of matrices):

float2x2 matrixCompMult (float2x2 x, float2x2 y) Returns the component-wise multiplication x by y
float3x3 matrixCompMult (float3x3 x, float3x3 y)
float4x4 matrixCompMult (float4x4 x, float4x4 y)

These functions compare vectors by component and return a boolean value of the same dimension (observing the order of comparison):

bool2 lessThan (int2 x, int2 y) Returns componentwise comparison x <y
bool3 lessThan (int3 x, int3 y)
bool4 lessThan (int4 x, int4 y)
bool2 lessThan (float2 x, float2 y)
bool3 lessThan (float3 x, float3 y)
bool4 lessThan (float4 x, float4 y)

bool2 lessThanEqual (int2 x, int2 y) Returns componentwise comparison x <= y
bool3 lessThanEqual (int3 x, int3 y)
bool4 lessThanEqual (int4 x, int4 y)
bool2 lessThanEqual (float2 x, float2 y)
bool3 lessThanEqual (float3 x, float3 y)
bool4 lessThanEqual (float4 x, float4 y)

bool2 greaterThan (int2 x, int2 y) Returns the componentwise comparison x> y
bool3 greaterThan (int3 x, int3 y)
bool4 greaterThan (int4 x, int4 y)
bool2 greaterThan (float2 x, float2 y)
bool3 greaterThan (float3 x, float3 y)
bool4 greaterThan (float4 x, float4 y)

bool2 greaterThanEqual (int2 x, int2 y) Returns componentwise comparison x> = y
bool3 greaterThanEqual (int3 x, int3 y)
bool4 greaterThanEqual (int4 x, int4 y)
bool2 greaterThanEqual (float2 x, float2 y)
bool3 greaterThanEqual (float3 x, float3 y)
bool4 greaterThanEqual (float4 x, float4 y)

bool2 equal (int2 x, int2 y) Returns the componentwise comparison x == y
bool3 equal (int3 x, int3 y)
bool4 equal (int4 x, int4 y)
bool2 equal (float2 x, float2 y)
bool3 equal (float3 x, float3 y)
bool4 equal (float4 x, float4 y)
bool2 equal (bool2 x, bool2 y)
bool3 equal (bool3 x, bool3 y)
bool4 equal (bool4 x, bool4 y)

bool2 notEqual (int2 x, int2 y) Returns the componentwise comparison x! = y
bool3 notEqual (int3 x, int3 y)
bool4 notEqual (int4 x, int4 y)
bool2 notEqual (float2 x, float2 y)
bool3 notEqual (float3 x, float3 y)
bool4 notEqual (float4 x, float4 y)
bool2 notEqual (bool2 x, bool2 y)
bool3 notEqual (bool3 x, bool3 y)
bool4 notEqual (bool4 x, bool4 y)

These functions work only with logical type vectors:

bool any (bool2 x) Returns true if at least one x is true
bool any (bool3 x)
bool any (bool4 x)

bool all (bool2 x) Returns true if all x elements are true
bool all (bool3 x)
bool all (bool4 x)

bool2 not (bool2 x) Returns the result of elementwise logical negation
bool3 not (bool3 x)
bool4 not (bool4 x)

PS: This is my first post on Habré. Please do not kick much;)

Source: https://habr.com/ru/post/84396/


All Articles