Aug
30
2011

Introducing EasyAGAL

Like most Flash developers out there, I’ve been getting excited about all the new possibilities Molehill is going to open up. So I’ve begun refreshing my somewhat shaky knowledge of matrix mathematics, and learning the new AGAL language. I could never understand why assembly code is always written in what looks more like shorthand than a fully expressed language, considering whatever the name of an operation is, it’ll be compiled down to a handful of bits understandable only to the CPU. Mario Scabia is absolutely spot on likening it to the ancient hieroglyphics, in his introduction to AGAL.

Learning how to work with matrices to achieve rendering effects is challenging enough without having to take on a new and strange programming language. Given that there is no IDE especially for AGAL (at least for the time being!) I decided to write a small library that would assist me in writing AGAL programs, just as easily as writing ActionScript. So, what does that mean?

  • Code completion and hinting
  • Far more easily readable code
  • Dynamic coding advantages

Two Flavors: Easy & Easier

Two base classes are provided for you to choose from: EasyAGAL.as which uses the original AGAL opcodes for function names, and EasierAGAL.as which uses fully expressed function names.

Compare these corresponding samples:

	"m44 vt1, va2, vc8 \n" +
	"nrm vt1.xyz, vt1.xyz \n" +
	"sub vt2, vc12, vt0 \n" +
	"nrm vt2.xyz, vt2.xyz \n" +
	"dp3 vt3, vt1, vt2 \n" +
	"mov v2, vt3"
	// With EasyAGAL...
 
	m44( TEMP[1], ATTRIBUTE[2], CONST[8] );
	nrm( TEMP[1].xyz, TEMP[1].xyz );
	sub( TEMP[2], CONST[12], TEMP[0] );
	nrm( TEMP[2].xyz, TEMP[2].xyz );
	dp3( TEMP[3], TEMP[1], TEMP[2] );
	mov( VARYING[2], TEMP[3] );
	// or with EasierAGAL...
 
	multiply4x4( TEMP[1], ATTRIBUTE[2], CONST[8] );
	normalize( TEMP[1].xyz, TEMP[1].xyz );
	subtract( TEMP[2], CONST[12], TEMP[0] );
	normalize( TEMP[2].xyz, TEMP[2].xyz );
	dotProduct3( TEMP[3], TEMP[1], TEMP[2] );
	move( VARYING[2], TEMP[3] );

You’ll notice that the EasyAGAL code simplifies the use of registers a bit — depending on whether you’re writing a vertex or a fragment shader, the appropriate register will automatically be used. So, for example, you don’t need to worry about vt1 versus ft1, only TEMP[1] which will be translated appropriately. We can make the EasyAGAL code more readable still, by assigning registers to variables with descriptive names:

	var normal:IRegister = ATTRIBUTE[2];
	var normalMatrix:IRegister = CONST[8];
	var xformedNorm:IRegister = TEMP[1];
	var intensity:IRegister = TEMP[2];
 
	multiply4x4( xformedNorm, normal, normalMatrix );
	normalize( xformedNorm.xyz, xformedNorm.xyz );
	subtract( intensity, CONST[12], TEMP[0] );
	normalize( intensity.xyz, intensity.xyz );
	dotProduct3( TEMP[3], TEMP[1], intensity );
	move( VARYING[2], TEMP[3] );

Skeptical?

Some may say “PixelBender3D does the same thing…” …which is actually quite inaccurate. PixelBender3D is a high level language that is pre-compiled down to AGAL byte-code. When writing AGAL from ActionScript (with or without the aid of this library) we have the oportunity to dynamically make some decisions about how the shader is written, e.g. whether to include vertex fogging, etc. We can instantly rewrite the shader to include or exclude any number of options. True, PixelBender3D was created as a friendlier alternative to AGAL, but at some cost to efficiency and outright hands-on control.

Others will say, “If you take the time to learn AGAL properly, you’ll be able to read it more easily and you won’t need any of this.” I expect that for many the hurdle of making sense out of the hieroglyphics of AGAL when first meeting the language will prove too much of an obstacle to progress beyond basic tutorials. This library provides training wheels to learning AGAL. I have not reinvented the language, but merely made it much easier to read and write, leveraging the features of our IDE’s. All methods of EasyAGAL and EasierAGAL maintain the same parameters, in the same order, as AGAL opcodes; They are all documented with ASDoc tags providing help for every instruction and every register as you type. The code-hints from EasierAGAL also include the original AGAL opcodes to help you learn them.

Happy Trails

AGAL is not easy, but hopefully this library will make it easier, and assist your learning experience. Here are some excellent links to tutorials and introductions to AGAL and the Molehill API:

My Name is AGAL, and I Come from Adobe by Marco Scabia
Molehill – Getting Started by Mikko Haapoja
Tutorials by Pixelante

Once you’ve explored some of these tutorials and are ready to try your hand at coding some AGAL, please visit the repository for my new open source project EasyAGAL now on GitHub.

Written by barliesque in: AS3,Molehill | Tags: , , , , , , ,

19 Comments »

  • Jim

    Really like the look of this. Will definitely be a useful tool.

    Thanks!

    Comment | 22.Oct.11
  • [...] 相关内容:http://studio.barliesque.com/blog/2011/08/introducing-easyagal/ [...]

    Pingback | 23.Oct.11
  • Daniele Barell

    Hi David. Great initiative!
    What about making some ASDocs?

    dan

    Comment | 24.Oct.11
  • Hi Dan, glad you like it.
    ASDocs are on my to do list — should have them ready sometime this week.

    Comment | 24.Oct.11
  • I’ve updated ASDocs throughout the source with lots of additional information and a few minor corrections. Full documentation is now included with EasyAGAL, or you can view it online here: http://barliesque.com/easy_agal/docs/

    Comment | 5.Nov.11
  • bjwulin

    very good,thks。

    Comment | 12.Nov.11
  • [...] http://studio.barliesque.com/blog/2011/08/introducing-easyagal [...]

    Pingback | 17.Nov.11
  • [...] To further facilitate writing Vertex and Fragment shaders in AGAL, I will be using EasyAGAL by Studio Barliesque (available on GitHub here or as a ZIP download [...]

    Pingback | 27.Dec.11
  • Hey, great library! Any chance you would have acos, asin and atan methods available in there at some point? Would be neat to delegate extra trigonometric work on the GPU :)

    Comment | 5.Jan.12
  • Hi Pierre,
    Thank you. I’ve been meaning to say hello and thank you for posting that nice tutorial on your blog.
    I have a lot of plans for EasyAGAL (more plans than *time* lately!) including some more useful macros to add to the library. I’ll be adding a few new goodies in the next week. I’ll try to make time for those geometry functions as well. :) I have found a lot of mathematical functions turn out to be better off pre-calculated and then passed into the shader. I’m curious to know, how will you use those functions?

    Comment | 6.Jan.12
  • Hey David, thanks for checking out my blog too!

    Can’t wait to see those geometric methods available :) (When you do, could you please let me know and/or write a new blog post to notify people about it!)

    I’m mostly experimenting right now just with Quads (for 2d rendering only at this time) to see how I can change the position, color information, UV coordinates and rotation of an object on the GPU with vertex/fragment shaders.

    The one property I’m having trouble implementing is the rotation. Basically, I want the position information in the vertex-data to remain flat (0-degrees), I don’t want to pre-rotate those points in AS3, I want to try using trigonometry in AGAL to delegate the work on the GPU.

    In order to do that though… since the 4 vertices are related to eachother (because they form the Quad) and must use some common information, I have to repeat 4 times:
    - Where the pivot point is located (X and Y = 2 floats).
    - What is the angle (rotation) of the object (1 float).

    So with an AGAL method such as ATAN2, it would help solve what is the current angle between the pivot-point and a vertex in the Quad. I could then use that angle information (along with the distance information, which you already have in EasyAGAL!) and add it with the rotation property amount to make it look like it’s turning around the pivot point.

    Maybe if I show you what my vertex-data format looks like it would clarify what I’m after:

    v0: 0,0, 0,0, 2,3, 2,2, 45
    v1: 5,0, 1,0, 2,3, 2,2, 45
    v2: 5,5, 1,1, 2,3, 2,2, 45
    v3: 0,5, 0,1, 2,3, 2,2, 45

    So the first 2 numbers in each vertices indicate the Width & Height of the object. The next two indicate the UV map coordinates on a texture. The third pair of numbers are the X & Y Offset to translate the object vertically / horizontally (these would be the same values for all 4 vertices). The 4th pair is the X & Y pivot point (Where the object will perform it’s rotation around). Finally, the last value is the rotation amount (here in degrees, but could be in radians to save on conversions of degrees-to-radians operations).

    Hopefully that makes some sense! If you notice any wrong approach to what I’m doing I wouldn’t mind some criticism as I’m new to this GPU stuff.

    Have a nice Monday!

    Comment | 9.Jan.12
  • As you saw from the asgl library, it takes quite a few instructions to do an atan2() or acos(). Performing those instructions over and over for every single vertex that needs to be rendered ends up being a lot of redundant processing.

    Your best bet here is to precalculate that rotation from AS3, not into the geometry, but into a transformation matrix that you’ll pass into the shader as a constant. Molehill will then apply that to the geometry.

    Also, the (X,Y) offset coordinate doesn’t really belong in the vertex information — that’s actually a part of the transformation matrix as well. A 3×3 matrix can contain position, rotation, scale and skew information, all of which gets instantly applied at once with a single matrix multiply instruction.

    Here’s a link to an excellent article about 2D transformation matrices:
    http://www.senocular.com/flash/tutorials/transformmatrix/

    Comment | 9.Jan.12
  • Hmm okay, but what if I need unique transformations for each individual squares / quads?

    Example:
    - One rotated at 45 degrees;
    - One scaled at 110%;
    - One flipped horizontally;

    Won’t I need a matrix per objects? I’m not sure how one matrix could control all of the geometry.

    Plus, even if the AGAL limitation of 128 constants (in a vertex-shader) sounds sufficient in most cases, I’d rather use a solution that can allow for much more object transformations, especially if they will be nested in a similar fashion like the existing DisplayList hierarchy.

    If you tried to accomplish these individual transforms for each instances, would you do it from AS3 first?

    I’m thinking I’ll have to store the position, rotation and scale as separate properties in the AS3 class of my object, and then when it’s required by the GPU I can perform the Matrix calculation and pass a Vector.[Number] of the resulting vertices locations. I would think that would have less impact than running the huge atan2() instructions on the GPU (I don’t think I would even have to use atan2() in AS3 either with the use of Matrices).

    Comment | 10.Jan.12
  • Oh Thanks for that Senocular Transform Matrix link too, btw!

    Comment | 10.Jan.12
  • The idea is to upload your geometry only once, and upload transformation matrices for each quad at render-time. Only use ActionScript to handle the preparation of the transform matrices of each of your quads. Then use AGAL to apply the transform matrices to the geometry.

    You could write a shader to render a batch of quads, as many quads as possible given the max of 128 vertex constants. Or you could repeatedly call a shader that renders a single quad at a time. I suspect the best performance balance will be a combination of those ideas.

    I would have a look at the source of ND2D or Starling for an example of how to handle rendering a large number of quads.

    Comment | 10.Jan.12
  • [...] if you search online. I’ll also be using David Barlia’s EasyAGAL library (see here for more details) – because I definitely need a helping hand with coding shaders that are [...]

    Pingback | 8.Mar.12
  • Alexander

    how it do this?I will check it, thanks for your codes.

    Comment | 9.Apr.12
  • Alexander

    thanks for your codes.

    Comment | 9.Apr.12
  • glory

    I am glory I like what u are doing its fine I love it

    Comment | 25.Apr.12

RSS feed for comments on this post. TrackBack URL


Leave a comment!

NOTE: All comments are moderated, so may take a day or two to appear.

Powered by WordPress | Theme based on Aeros by theBuckMaker | Admin