Friday, September 05, 2008

Pixel Bender .pbj files

If you have been playing with Pixel Bender in Flash Player 10 you know the workflow:
  • Create your .pbk in the Pixel Bender Toolkit.
  • Export a .pbj binary from the Pixel Bender Toolkit.
  • Embed or dynamically load the .pbj file in your ActionScript.
There is still some mystery around .pbj files, i.e. the file format is neither documented nor is it clear what exactly it contains. While I can't offer documentation on the file format at this time (although that will happen eventually) what I can offer is an assembler and disassembler I quickly hacked together. I am mostly using for this my own debugging purposes. For those who want to tweak Pixel Bender in Flash to the max this is a really good way to go.

Please note that this is neither officially supported by Adobe nor do I guarantee any correctness or completeness of these two tools. The binary format could change at any time, you should not rely on it. I am really throwing this out to the world for educational purposes. There is no documentation on the syntax or format nor how to put together kernels from scratch. It's really up to you to make any sense out of it and I do not expect that any Adobe will ever use this syntax since I just made it up myself. Since these are a quite advanced tools I also assume you know how to compile C++ command line tools yourself ;-)

Enough disclaimers, here is the meat:

http://www.kaourantin.net/source/pbjtools/apbj.cpp
http://www.kaourantin.net/source/pbjtools/dpbj.cpp

But for the lazy I have pre-compiled two Windows binaries of these two command line tools. On OSX you can simply compile these using 'g++ apbj.cpp -o apbj' and 'g++ dpbj.cpp -o dpbj' if you have the developer tools installed on your system. Here are the Windows binaries:

http://www.kaourantin.net/source/pbjtools/apbj.zip
http://www.kaourantin.net/source/pbjtools/dpbj.zip

It should be fairly clear on how to use these if you run them in a command prompt. One of the goals was to allow perfect round tripping, i.e. disassemble->assemble->disassemble without any information loss. I hope I succeeded in this. I also know that someone has already put together an ActionScript version of this which is quite easily done.

Here is some sample output of the disassembler, the .pbj file was based on a Pixel Bender kernel created by Mr.doob (and btw, I fixed the bug he noticed in his blog entry ;-):


version 1
name "NewFilter"
kernel "namespace", "Hypnotic"
kernel "vendor", "Mr.doob"
kernel "version", 1
kernel "description", "Hypnotic effect"

parameter "_OutCoord", float2, f0.rg, in

texture "src", t0

parameter "dst", float4, f1, out

parameter "imgSize", float2, f0.ba, in
meta "defaultValue", 512, 512
meta "minValue", 0, 0
meta "maxValue", 512, 512

parameter "center", float2, f2.rg, in
meta "defaultValue", 256, 256
meta "minValue", 0, 0
meta "maxValue", 512, 512

parameter "offset", float2, f2.ba, in

;----------------------------------------------------------

mov f3.rg, f0.rg
sub f3.rg, f2.rg
rcp f3.ba, f0.ba
mul f3.ba, f3.rg
mov f3.rg, f3.ba
set f3.b, 3.14159
mov f3.a, f3.g
atan2 f3.a, f3.r
mov f4.r, f3.a
set f3.a, 2
mov f4.g, f3.r
pow f4.g, f3.a
set f3.a, 2
mov f4.b, f3.g
pow f4.b, f3.a
mov f3.a, f4.g
add f3.a, f4.b
sqr f4.g, f3.a
mov f3.a, f4.g
set f4.g, 0
set f4.b, 0
set f4.a, 0
add f4.g, f2.b
add f4.b, f2.a
cos f5.r, f4.r
rcp f5.g, f3.a
mul f5.g, f5.r
add f4.g, f5.g
sin f5.r, f4.r
rcp f5.g, f3.a
mul f5.g, f5.r
add f4.b, f5.g
set f5.r, 1
set f5.g, 0.1
mov f5.b, f3.a
pow f5.b, f5.g
rcp f5.g, f5.b
mul f5.g, f5.r
add f4.a, f5.g
mul f4.g, f0.b
mul f4.b, f0.a
set f5.r, 0
ltn f4.g, f5.r
mov i1.r, i0.r

if i1.r

set f5.r, 0
sub f5.r, f4.g
rcp f5.g, f0.b
mul f5.g, f5.r
ceil f5.r, f5.g
mov f5.g, f0.b
mul f5.g, f5.r
add f4.g, f5.g

end

set f5.r, 0
ltn f4.b, f5.r
mov i1.r, i0.r

if i1.r

set f5.r, 0
sub f5.r, f4.b
rcp f5.g, f0.a
mul f5.g, f5.r
ceil f5.r, f5.g
mov f5.g, f0.a
mul f5.g, f5.r
add f4.b, f5.g

end

ltn f0.b, f4.g
mov i1.r, i0.r

if i1.r

rcp f5.r, f0.b
mul f5.r, f4.g
floor f5.g, f5.r
mov f5.r, f0.b
mul f5.r, f5.g
sub f4.g, f5.r

end

ltn f0.a, f4.b
mov i1.r, i0.r

if i1.r

rcp f5.r, f0.a
mul f5.r, f4.b
floor f5.g, f5.r
mov f5.r, f0.a
mul f5.r, f5.g
sub f4.b, f5.r

end

mov f5.r, f4.g
mov f5.g, f4.b
texn f6, f5.rg, t0
mov f1, f6
mul f1.rgb, f4.aaa

4 Comments:

Blogger Mr.doob said...

Good to know that it wasn't a bug in my code and that it has been already fixed. Thanks once again Tinic!

Friday, September 05, 2008 9:46:00 PM  
Blogger Erki Esken said...

Trying to compile under OS X 10.5 I got this error:

$ g++ dpbj.cpp -o dpbj
dpbj.cpp:39:20: error: malloc.h: No such file or directory
dpbj.cpp: In function ‘const char* readStrN(int32_t)’:
dpbj.cpp:308: error: ‘malloc’ was not declared in this scope

Fix was to change #include <malloc.h> to #include <cstdlib> in dpbj.cpp file.

Saturday, September 06, 2008 11:31:00 AM  
Blogger Joa said...

I posted a first example of the ActionScript version at my blog.

There is still a lot to do (especially implementing op codes) but I will be able to release the sources hopefully soon.

Monday, September 08, 2008 6:41:00 AM  
Blogger yonatan said...

AS3 port of apbj: http://wonderfl.net/code/ff8dbc0a3468ef771745856eb977672e61cf0fdb/fullscreen

It's not as elegant as hxformat or pbjAS, but it does let you play with the assembler in your browser.

Friday, March 26, 2010 6:43:00 AM  

Post a Comment

<< Home