Fork me on GitHub

All you need is a Shader

var shader : Shader = new Shader( Context3DProgramType.FRAGMENT );

shader.mov( oc, c0 );

var agal : ByteArray = shader.complete();

In Instagal, registers have the same name in vertex or fragment shader, there is no vc0 , ft3 , va2 , but just c0 , t3 , a2

shader.mov( t0, c0 );
shader.m44( t0, t0, c1 );
shader.mov( oc, t0 );
						

Use XOR ^ operand to mask register components

shader.mov( t0 ^ xy, c0 ^ wz );
shader.mov( xy ^ t0, wz ^ c0 ); // it's a real xor op

Note that in agal vt0.xyyy is the same than vt0.xy. Masks like xyyy are no defined in Instagal's constants, use xy instead.

You can use addition or substraction to offset a register

var i : int = 5;
shader.mov( t0+i, c4 );
// "mov vt5, vc4 "

Following examples produce the same agal bytecode.

shader.mov( t5, c4 );
shader.mov( t2 + 3, c6 - 2 );
var i : int = 3;
shader.mov( t2 + i, c7 - i );

Of course, it also work with mask

shader.mov( t2 + 3 ^ xyz, c6 - 2 ^ xyz );
shader.mov( t2 ^ xyz + 3, c6 ^ xyz - 2 );

var i : int = 3;
shader.mov( t2 + i ^ xyz, c7 - i ^ xyz );

Simply use pipe | , or OR operand, to define samplers options

shader.tex( t0, v0 ^ xy, s0 | Tex.REPEAT | Tex.LINEAR | Tex.MIPLINEAR );

You can omit options. This produce 2d, nearest, nomip, clamp, rgba sampler

shader.tex( t0, v0 ^ xy, s0 );

To apply a LOD bias, use Tex.bias() method like other options

shader.tex( t0, v0 ^ xy, s0 | Tex.REPEAT | Tex.bias( 6.4 ) );

And like other registers, you can offset sampler index with a simple addition

shader.tex( t0, v0 ^ xy, s0+4 | Tex.REPEAT );

In agal you can write vc[vt0.y] to define "indirect" register. To achieve the same in Instagal use the provided c() global Function

Note that Indirect register are only available on vertex constants registers ( vc ), that'w why there is no a(), t() or v() functions.

shader.mov( t0, c( t0^y ) );
// mov vt0, vc[vt0.y]

To add an offset to indirect registers vc[vt0.y+4] , simply add it to the function result. Indirect offsets must be positive.

shader.mov( t0, c( t0^y ) + 4 );

For more flexibility, Instagal provide ShaderChunks objects. ShaderChunks are incomplete shader parts which can be append to a Shader to produce the final bytecode.

ShaderChunks behave exactly the same than Shader object, except they have no constructor options (they don't care about "vertex" or "fragment")

var projection : ShaderChunk = new ShaderChunk();
projection.m44( t0, a0, c1 );
projection.m33( v0, a1, c1 );

var texcoord : ShaderChunk = new ShaderChunk();
texcoord.mov( v1, a2 );

var shader : Shader = new Shader( Context3DProgramType.VERTEX );
shader.append( projection );
shader.append( texcoord );
shader.mov( op, t0 );

var agal : ByteArray = shader.complete();

instagal.swc v1.0RC3 (29/03/2013)

Adobe's AgalMiniAssembler vs Instagal.


var frame : int = 200; // ms
var agal : ByteArray;


// fairplay, create only one assembler
var ama : AGALMiniAssembler = new AGALMiniAssembler();

// fairplay, construct the code out of the loop
var vertexCode : String =  [
	"mov vt0, va0",
	"mov vt2, va2",
	"m44 vt7, vt0, vc0",
	"mul op, vt7, vc4",
	"mov v0, va1",
	"m44 vt1.xyz, vt0, vc5",
	"mov vt1.w, vt0.w",
	"m33 vt3.xyz, vt2.xyz, vc9",
	"mov vt3.w, vt2.w",
	"mov v1, vt3",
	"sub vt2, vc13, vt1",
	"nrm vt4.xyz,vt2.xyz",
	"dp3 vt1.w, vt3.xyz, vt4.xyz",
	"sub v2.w, vc13.w, vt1.w",
	"add vt1.w, vt1.w, vt1.w",
	"mul vt1.xyz, vt3.xyz, vt1.w",					
	"sub vt1.xyz, vt1.xyz, vt4.xyz",				
	"nrm v2.xyz, vt1.xyz" 
].join( '\n' );

var fragmentCode : String =  [
	"mov ft0 	   ,  fc2",
	"tex ft1 	   ,  v1      , fs0 <cube,nearest,clamp>",
	"div ft1.w     ,  ft1.w   , fc0.z",
	"sub ft1.w     ,  ft1.w   , fc3.y",
	"pow ft1.w     ,  fc3.x   , ft1.w",
	"mul ft1.xyz   ,  ft1.xyz , ft1.w",
	"mul ft1.xyz   ,  ft1.xyz , fc3.z",
	"mul ft0.xyz   ,  ft1.xyz , ft0.xyz	",
	"tex ft1       ,  v2.xyz  , fs1 <cube,nearest,clamp>",
	"div ft1.w     ,  ft1.w   , fc0.z",
	"sub ft1.w     ,  ft1.w   , fc4.z",
	"pow ft1.w     ,  fc4.x   , ft1.w",
	"mul ft1.xyz   ,  ft1.xyz , ft1.w",
	"pow ft1.w     ,  v2.w    , fc4.y",
	"mul ft1.w     ,  ft1.w   , fc1.w",
	"add ft1.w     ,  ft1.w   , fc1.z",
	"mul ft1.xyz   ,  ft1.xyz , ft1.w",
	"add ft0.xyz   ,  ft0.xyz , ft1.xyz",			
	"tex ft1       ,  v0      , fs2 <2d,nearest,clamp,dxt1>",
	"mul ft0.xyz   ,  ft0.xyz , ft1.x",
	"mul ft0.xyz   ,  ft0.xyz , fc5.x",
	"pow ft0.xyz   ,  ft0.xyz , fc5.y",
	"mov oc        ,  ft0"
].join( '\n' );

var st : int;

st = getTimer();

// fairplay, use "vertex" litteral
while( getTimer() - st < frame){
	agal = ama.assemble( "vertex", vertexCode );
	compileNum++;
}

st = getTimer();

// fairplay, use "fragment" litteral
while( getTimer() - st < frame){
	agal = ama.assemble( "fragment", fragmentCode );
	compileNum++;
}
								
var s : Shader;
var frame : int = 200;
var agal : ByteArray = new ByteArray();
var st : int;

st = getTimer();

while( getTimer() - st < frame){
	s = new Shader( Context3DProgramType.VERTEX );
	
	s.mov( t0,     a0               );
	s.mov( t2,     a2	             );
	s.m44( t7,     t0,       c0     );
	s.mul( op,     t7,       c4     );
	s.mov( v0,     a1               );
	s.m44( t1^xyz, t0,       c5     );
	s.mov( t1^w,   t0^w             );
	s.m33( t3^xyz, t2^xyz,   c9     );
	s.mov( t3^w,   t2^w             );
	s.mov( v1,     t3               );
	s.sub( t2,     c13,      t1     );
	s.nrm( t4^xyz, t2^xyz           );
	s.dp3( t1^w,   t3^xyz,   t4^xyz );
	s.sub( v2^w,   c13^w,    t1^w   );
	s.add( t1^w,   t1^w,     t1^w   );
	s.mul( t1^xyz, t3^xyz,   t1^w   );
	s.sub( t1^xyz, t1^xyz,   t4^xyz );
	s.nrm( v2^xyz, t1^xyz           );
	
	s.writeBytes( agal );
	
	compileNum++;
}

st = getTimer();

while( getTimer() - st < frame){
	s = new Shader( Context3DProgramType.FRAGMENT );
	s.mov( t0 	   , c2        );      
	s.tex( t1 	   , v1       ,s0 
		| Tex.CUBE | Tex.NEAREST | Tex.CLAMP );
	s.div( t1^w   , t1^w     ,c0^z	  );
	s.sub( t1^w   , t1^w     ,c3^y	  );
	s.pow( t1^w   , c3^x     ,t1^w	  );
	s.mul( t1^xyz , t1^xyz   ,t1^w	  );
	s.mul( t1^xyz , t1^xyz   ,c3^z	  );
	s.mul( t0^xyz , t1^xyz   ,t0^xyz );
	s.tex( t1     , v2^xyz   ,s1 
		| Tex.CUBE | Tex.NEAREST | Tex.CLAMP );
	s.div( t1^w   , t1^w     ,c0^z	  );
	s.sub( t1^w   , t1^w     ,c4^z	  );
	s.pow( t1^w   , c4^x     ,t1^w	  );
	s.mul( t1^xyz , t1^xyz   ,t1^w	  );
	s.pow( t1^w   , v2^w     ,c4^y	  );
	s.mul( t1^w   , t1^w     ,c1^w	  );
	s.add( t1^w   , t1^w     ,c1^z	  );		
	s.mul( t1^xyz , t1^xyz   ,t1^w	  );			
	s.add( t0^xyz , t0^xyz   ,t1^xyz );
	s.tex( t1     , v0       ,s2
		| Tex.NEAREST | Tex.CLAMP | Tex.DXT1 );
	s.mul( t0^xyz , t0^xyz   ,t1^x   );
	s.mul( t0^xyz , t0^xyz   ,c5^x   );
	s.pow( t0^xyz , t0^xyz   ,c5^y   );
	s.mov( oc     , t0               );
	
	s.writeBytes( agal );
	
	compileNum++;
}