本帖最后由 sleep2death 于 2011-4-20 16:49 编辑
应7yue大大的要求,贴写小东西.
package shader {
import flash.display3D.*;
import flash.display3D.textures.*;
import flash.geom.Matrix3D;
import com.adobe.utils.*;
public class AGALHelper {
public static var context : Context3D;
public static var program : Program3D;
public static var vaNames : Vector.<String> = new Vector.<String>(8); // MAX 8
public static var fsNames : Vector.<String> = new Vector.<String>(8); // MAX 8
public static var vcNames : Vector.<String> = new Vector.<String>(128); // MAX 128
public static var fcNames : Vector.<String> = new Vector.<String>(28); // MAX 28
public static var vtNames : Vector.<String> = new Vector.<String>(8); // MAX 8
public static var ftNames : Vector.<String> = new Vector.<String>(8); // MAX 8
public static var vNames : Vector.<String> = new Vector.<String>(8); // MAX 8
public static const FLOAT : uint = 0;
public static const FLOAT2 : uint = 1;
public static const FLOAT3 : uint = 2;
public static const FLOAT4 : uint = 3;
public static const VERTEX : uint = 0;
public static const FRAMENT : uint = 1;
public static function getAttributeIndex(name : String) : int {
var insertIndex : int = vaNames.indexOf(name);
if(insertIndex < 0) {
insertIndex = vaNames.indexOf(null);
vaNames[insertIndex] = name;
trace("assign " + name + " to va" + insertIndex);
}
return insertIndex;
}
public static function setAttribute(name : String, buffer : VertexBuffer3D, offset : uint = 0, format : String = "float4") : void {
context.setVertexBufferAt(getAttributeIndex(name), buffer, offset, format);
}
public static function getVertexConstantIndex(name : String) : int {
var insertIndex : int = vcNames.indexOf(name);
if(insertIndex < 0) {
insertIndex = vcNames.indexOf(null);
vcNames[insertIndex] = name;
trace("assign " + name + " to vc" + insertIndex);
}
return insertIndex;
}
public static function setVertexConstant(name : String, value : *) : void {
if(value is Vector.<Number>){
context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, getVertexConstantIndex(name), value);
}else if(value is Matrix3D){
context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, getVertexConstantIndex(name), value, true);
}
}
public static function getFragmentConstantIndex(name : String) : int {
var insertIndex : int = fcNames.indexOf(name);
if(insertIndex < 0) {
insertIndex = fcNames.indexOf(null);
fcNames[insertIndex] = name;
trace("assign " + name + " to fc" + insertIndex);
}
return insertIndex;
}
public static function setFragmentConstant(name : String, value : *) : void {
if(value is Vector.<Number>){
context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, getVertexConstantIndex(name), value);
}else if(value is Matrix3D){
context.setProgramConstantsFromMatrix(Context3DProgramType.FRAGMENT, getVertexConstantIndex(name), value, true);
}
}
public static function getSampleIndex(name : String) : int {
var insertIndex : int = fsNames.indexOf(name);
if(insertIndex < 0) {
insertIndex = fsNames.indexOf(null);
fsNames[insertIndex] = name;
trace("assign " + name + " to fs" + insertIndex);
}
return insertIndex;
}
public static function setSample(name : String, value : Texture) : void {
context.setTextureAt(getSampleIndex(name), value);
}
public static function getIndexByName(vf : String, type : String, name : String) : uint {
var first : String = type == "v" ? "v" : vf + type;
var names : Vector.<String> = AGALHelper[first + "Names"];
var insertIndex : int = names.indexOf(type + "_" + name);
if(insertIndex < 0) {
insertIndex = names.indexOf(null);
names[insertIndex] = type + "_" + name;
trace("assign " + type + "_" + name + " to " + first + insertIndex);
}
return insertIndex;
}
public static var v_code : String = new String();
public static function addVertexCode(op_code : String, out : String, in1 : String ,in2 : String = null, extra : String = null) : void {
if(op_code == "len"){
ExtraCode_len(out, in1);
}else{
v_code += op_code + " " + parseParam(out, "v") + ", " + parseParam(in1, "v");
if(in2 != null) v_code += " " + parseParam(in2, "v");
if(extra != null) v_code +=" " + extra;
v_code += " \n";
}
}
public static var f_code : String = new String();
public static function addFragmentCode(op_code : String, out : String, in1 : String ,in2 : String = null, extra : String = null) : void {
f_code += op_code + " " + parseParam(out, "f") + ", " + parseParam(in1, "f");
if(in2 != null) f_code += " " + parseParam(in2, "f");
if(extra != null) f_code +=" " + extra;
f_code += " \n";
}
private static var v_assembler : AGALMiniAssembler = new AGALMiniAssembler();
private static var f_assembler : AGALMiniAssembler = new AGALMiniAssembler();
public static function uploadCode() : void {
v_assembler.assemble(Context3DProgramType.VERTEX, v_code);
f_assembler.assemble( Context3DProgramType.FRAGMENT, f_code);
if(!program){
program = context.createProgram();
context.setProgram(program);
}
program.upload(v_assembler.agalcode, f_assembler.agalcode);
}
public static function printCode() : void {
trace("======== VERTEX ========");
trace(v_code);
trace("======== FRAGMENT ========");
trace(f_code);
}
private static function parseParam( code : String, vf : String ) : String {
var prop : Array = code.split(".");
var prop_str : String;
if(prop.length > 1) {
code = prop[0];
prop_str = "."+prop[1];
}else{
prop_str = "";
}
var codes : Array = code.split("_");
if(codes.length > 1)
return (codes[0] == "v" ?"" : vf) + codes[0] + getIndexByName(vf, codes[0], codes[1]) + prop_str;
return code + prop_str;
}
private static function ExtraCode_len(out : String, in1 : String) : void {
addVertexCode("dp3", out, in1, in1);
addVertexCode("sqr", out, out);
}
}
}
如何使用呢?
先用helper设置一些属性:
AGALHelper.setVertexConstant("c_a1", Vector.<Number>([1.025]));
AGALHelper.setAttribute("a_vb", vertexBuffer));
然后写汇编
AGALHelper.addVertexCode("mov", "t_vb", "a_vb");
AGALHelper.addVertexCode("mov", "t_uvb", "a_uvb");
AGALHelper.addVertexCode("mov", "t_nb", "a_nb");
AGALHelper.addVertexCode("sub", "t_v3Ray", "t_vb", "c_v3CameraPos.xyz");
AGALHelper.addVertexCode("len", "t_fFar.xyz", "t_v3Ray");
AGALHelper.addVertexCode("m44", "op", "t_vb", "c_proj");
AGALHelper.addVertexCode("mov", "v_uvb", "t_uvb");
AGALHelper.addVertexCode("mov", "v_nb", "t_nb");
AGALHelper.addFragmentCode("mov", "t_uvb", "v_uvb");
AGALHelper.addFragmentCode("tex", "t_day", "t_uvb", "s_day", "<2d, clamp, linear>");
AGALHelper.addFragmentCode("mov", "oc", "t_day");
AGALHelper.printCode();
AGALHelper.uploadCode();
好处是你再也不要去记ft0, fc1到底是啥了...另外可以新增一些方法,比如length等等