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++; }