Molehill AGAL helper/wrapper… contributions welcome

NEW UPDATE COMING SOON (09.09.2011)- a few more functions and will proper code hints
UPDATE 19.05.2011
helper is now on google code
>>AGAL<<

these static functions ideally can help you build shaders in a more readable and more reusable way.
they are an incomplete set and require additions and improvement.

so feel free to post additions and alterations if I have cocked up somewhere (a good chance of that as I boshed this out in a rush)
and Ill see that they get worked in.

 
//util functions (this section is the one I would like to see grow)
 
//same as 'mix'
public static function lerp(target:String, source1:String, source2:String, ratio:String):String
{
	var code:String = "";
	code += sub(target, source2, source1);
	code += mul(target, target, ratio);
	code += add(target, target, source1);
	return code;
}
 
//should return the length of the source vector
public static function length(target:String, source:String):String
{
	var code:String = "";
	code += dp3(target, source, source);
	code += sqt(target, target);
	return code;
}
//calculates the reflection vector based on a view direction and a normal (formula:  r = V - 2(V.N)*N)
public static function reflect(target:String, view:String, normal:String):String
{
	var code:String = "";
	code += dp3(target+".w", view+".xyz", normal+".xyz");
	code += add(target+".w", target+".w", target+".w");
	code += mul(target+".xyz", normal+".xyz", target+".w");
	code += sub(target+".xyz", view+".xyz", target+".xyz");
	code += neg(target+".xyz", target+".xyz");
	return code;
}
 
//generic helpers (usefulness debatable)
 
//unit vector from Light to the Vertex position
public static function light(target:String, light:String, position:String):String
{
	var code:String = "";
	code += sub(target, position, light);
	code += nrm(target, target);
	return code;
}
//unit vector from Vertex P to the View position V
public static function view(target:String, position:String, camera:String):String
{
	var code:String = "";
	code += sub(target, camera, position);
	code += nrm(target, target);
	return code;
}
//unit vector halfway H, between L and V, used for Blinn simplification
public static function half(target:String, light:String, view:String):String
{
	var code:String = "";
	code += add(target, light, view);
	code += nrm(target, target);
	return code;
}
 
//wrappers for inbuilt functions (incomplete)
public static function mov(target:String, source:String):String
{
	return "mov " + target + " " + source + "\n";
}
public static function add(target:String, source1:String, source2:String):String
{
	return "add " + target + " " + source1 + " " + source2 + "\n";
}
public static function sub(target:String, source1:String, source2:String):String
{
	return "sub " + target + " " + source1 + " " + source2 + "\n";
}
public static function mul(target:String, source1:String, source2:String):String
{
	return "mul " + target + " " + source1 + " " + source2 + "\n";
}
public static function neg(target:String, source:String):String
{
	return "neg " + target + " " + source + "\n";
}
public static function sqt(target:String, source:String):String
{
	return "sqt " + target + " " + source + "\n";
}
public static function nrm(target:String, source:String):String
{
	return "nrm " + target + " " + source + "\n";
}
public static function dp3(target:String, source1:String, source2:String):String
{
	return "dp3 " + target + " " + source1 + " " + source2 + "\n";
}
public static function pow(target:String, source1:String, source2:String):String
{
	return "pow " + target + " " + source1 + " " + source2 + "\n";
}
public static function m33(target:String, source1:String, source2:String):String
{
	return "m33 " + target + " " + source1 + " " + source2 + "\n";
}
public static function tex(target:String, coord:String, texture:String, type:String, wrap:String, filter:String):String
{
	return "tex "+target+" "+coord+" "+texture+" <"+type+","+wrap+","+filter+">" + "\n";
}

🙂

as an idea for some of the functions what I could do is add and optional boolean parameter called normalize and if its set I could automatically normalize the output.

would like to see the following functions added:
refract (tried to do this one myself but got scared and ran away)
smoothstep (see wikipedia about this one… the problem is that it requires the use of a constant or two and ideally these wouldn’t have to be passed in as parameters.. any idea if that is possible?)
..and anything else anyone can think of that the api is currently misisng
and I’ll soon be putting in some lighting methods for helping people get diffuse and specular lighting.

8 Responses to “Molehill AGAL helper/wrapper… contributions welcome”

  1. mice.Lu says:

    pixelblender3D does the same thing…
    and it’s official

  2. […] I was just casually browsing com.adobe.utils when I came across AGALMacroAssembler. I’ve found it allows you to write much nicer looking code, faster. I’ve made a few macros for you based on Ben Whiting’s AGAL Helper. […]

  3. antyk says:

    Hey – I just went through the latest version of AGAL Helper from google code repo and I have a question. The Blinn Phong methods are implemented correctly? I have a bit hard time getting it to work :p

  4. bwhiting says:

    I think it was working last time I checked but I often tweak it.

    Feel free to post any code in here and I will take a look when I have some spare time, will have a proper check on Monday of the code on google.

  5. antyk says:

    And how are things? I went back to mine project today and have been trying to add the specular light, unfortunetly with no results. Are the Phong calcs ok? If so, can You paste a simple demo showing how You would it? I would be very greateful! 🙂

  6. bwhiting says:

    demo:
    http://www.bwhiting.co.uk/b3d/specular/

    code:
    //vertex
    AGAL.m44(ws_pos, ls_pos, m_mtx.register)+ //transform vertex into world space
    AGAL.view(view, ws_pos, camera.register) + //store view
    AGAL.light(light, light_register.register, ws_pos) + //store light
    AGAL.mov(view_out, view)+ //pass view to fragment shader
    AGAL.mov(light_out, light); //pass light to fragment shader
    AGAL.m33(normal_out+”.xyz”, normal_in, m_mtx.register)+ //transform normal into world space
    AGAL.mov(normal_out+”.w”, normal_in+”.w”); //set w component

    //fragment
    AGAL.nrm(normal+”.xyz”, normal_in) + //normalize the normal
    AGAL.specularBlinnPhong2(result, light, view, normal, specularData.register); //put the phong calculation into the result

    …then add that value to the current pixel colour. (or just send it out in “oc”)

    note:
    specularData[0] = ((_specularColour >> 16) & 0xff) / 0xff * _specularIntensity; //R
    specularData[1] = ((_specularColour >> 8) & 0xff) / 0xff * _specularIntensity; //G
    specularData[2] = ((_specularColour & 0xff)) / 0xff * _specularIntensity; //B
    specularData[3] = _specularShinniness; //A

    _specularIntensity defaults to 1; //0-1 range
    _specularShinniness defaults to 64; //1-512 recommended, 16-128 usually where you wanna be.

    Hope that helps.
    (in the link in the demo I have a texture * diffuse + specular as the material, the code above is just for the specular part)

  7. antyk says:

    Thanks! 🙂 It really helped! 🙂

  8. bwhiting says:

    glad it did, its not optimal code mind, the half vec could be calculated in the vertex shader and passed though instead of the light and view (then you would use the AGAL.specularBlinnPhong function not AGAL.specularBlinnPhong2)
    would have to remember to normalize the half though 😉

Leave a Reply