Alternativa3D系列 --着色系统
Alternativa3D 着色系统在一定意义上克服了AGAL汇编级代码的编写难度,实现了自己的一套编写规则,能进行寄存器变量声明和汇编命令行操作,
其着色语言 基本形式为:
"#v0=vUV", //v0为UV输入 "#s0=sDiffuse", //s0贴图输入,名字定义为sDiffuse "#c0=cThresholdAlpha",//透明度 "tex t0, v0, s0 <2d, linear,repeat, miplinear>", "mul t0.w, t0.w, c0.w",//w -alpha xyz - color "mov o0, t0"
"#"对变量进行声明,后会依据这个变量名 进行数据输入。 这样就不用去考虑寄存器索引的问题。
Alternativa3D 着色系统重要类:
ShaderProgram : 着色程序, 负责将着色代码传入到program.
vertexShader.link();//连接顶点着色器 fragmentShader.link();//链接片段着色器 program = context3D.createProgram();//创建着色程序 program.upload(vertexShader.data, fragmentShader.data);//上传着色器二进制代码
Linker: 着色链接器,可以加入不同的程序片断Procedure。声明寄存器,设置输入输出。
addProcedure:加入着色程序片断,可输入设置参数
declareVariable/declareSampler 声明寄存器
setInputParams/setOutputParams 声明输入输出
getVariableIndex 获取寄存器索引
link() 将Procedures 链接成一个 shader 将agal编译成二进制
1.编译头文件,2,解析各pass中的寄存器,3.写入各pass二进制代码
4.解析输入,输出寄存器,并设置输入输出寄存器索引,offset。
Procedure: 负责编译着色代码, 编译 声明及着色方法.
compileFromArray: 解析声明,编译命令,注入声明(供linker调用).
Variable: 寄存器基类, 子类定义各类寄存器,源寄存器,目标寄存器等等..
其主要用法:(源代码参见 TextureMaterial.collectDraws()方法)
一.获取program着色程序。(有,用缓存,无新建)
1. 设置着色程序,并上传到GPU中。
//建立顶点着色器 //声明属性寄存器 aPosition 并将其当成_projectProcedure的输入 //连接投影pass, positionVar为输入。 //关于projectProcedure //c0放入cProjMatrix 投影矩阵,输出为转换后的顶点。 //_projectProcedure = new Procedure(["m44 o0, i0, c0"], "projectProcedure"); //_projectProcedure.assignVariableName(VariableType.CONSTANT, 0, "cProjMatrix", 4); //数据输入:drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aPosition"), positionBuffer....); //连接uv Pass //new Procedure(["#v0=vUV", "#a0=aUV", "mov v0, a0"], "passUVProcedure"); //v0定义为vUV为片段着色器使用,a0定义为aUV,为顶点着色器输入UV数据 //数据输入:drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aUV"), uvBuffer,...); //数据输入: drawUnit.setProjectionConstants(camera, program.vertexShader.getVariableIndex("cProjMatrix"),....); var vertexLinker:Linker = new Linker(Context3DProgramType.VERTEX); var positionVar:String = "aPosition"; vertexLinker.declareVariable(positionVar, VariableType.ATTRIBUTE); //链接投影 vertexLinker.addProcedure(_projectProcedure); vertexLinker.setInputParams(_projectProcedure, positionVar); vertexLinker.addProcedure(_passUVProcedure); //声明片段着色器 //添加片段着色pass //new Procedure([ // "#v0=vUV", v0为UV输入 // "#s0=sDiffuse", //s0贴图输入,名字定义为sDiffuse // "#c0=cThresholdAlpha",//透明度 // "tex t0, v0, s0 <2d, linear,repeat, miplinear>", // "mul t0.w, t0.w, c0.w",//w -alpha xyz - color // "mov o0, t0" // ], "getDiffuseProcedure"); 片段着色代码 var fragmentLinker:Linker = new Linker(Context3DProgramType.FRAGMENT); fragmentLinker.addProcedure(getDiffuseProcedure); //将变寄存器对应 fragmentLinker.varyings = vertexLinker.varyings; //生成着色程序,并上传。 program = new ShaderProgram(vertexLinker, fragmentLinker); //upload时,会编译着色代码,此时会自动生成定义变量所对应的索引值。 program.upload(camera.context3D);
2.向GPU设置数据,向上面定义的变量中设置
//获取顶点 UV 缓冲数据 var positionBuffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.POSITION); var uvBuffer:VertexBuffer3D = geometry.getVertexBuffer(VertexAttributes.TEXCOORDS[0]); //建立此surface 下的drawUnit var drawUnit:DrawUnit = camera.renderer.createDrawUnit(.....); //设置顶点缓冲数据 drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aPosition"), positionBuffer....); //设置UV缓冲数据 drawUnit.setVertexBufferAt(program.vertexShader.getVariableIndex("aUV"), uvBuffer...); //设置变换矩阵 drawUnit.setProjectionConstants(camera, program.vertexShader.getVariableIndex("cProjMatrix"), object.localToCameraTransform); //设置透明度 drawUnit.setFragmentConstantsFromNumbers(program.fragmentShader.getVariableIndex("cThresholdAlpha"), alphaThreshold....); //设置贴图数据 drawUnit.setTextureAt(program.fragmentShader.getVariableIndex("sDiffuse"), diffuseMap._texture);