纳金网

标题: AGAL----BOX模糊 [打印本页]

作者: 家熊    时间: 2013-5-20 01:14
标题: AGAL----BOX模糊
本帖最后由 家熊 于 2013-5-20 01:31 编辑

这是式神的源码,先发布效果图[attach]35600[/attach]
下一节,将会对这个源码进行横向解析;
Main.as
package  
{
        import flash.display.*;
        import flash.display3D.*;
        import flash.display3D.textures.*;
        import flash.events.*;
        import flash.geom.*;
        import flash.text.TextField;
        import flash.utils.*;
        


        public class Main extends Sprite
        {
                [Embed(source="../res/plane.png")]
                private static var resClass:Class;
               
                public static var size:int = 256;
                //重绘区域大小
                private static var W:Number = 1024;
                private static var H:Number = 768;
               
                //场景
                private var context3D:Context3D;

                //显示对象
                private var sprite:Sprite2D
               
                public static var scale:Number=1
                public function Main():void
                {
                        stage.scaleMode = StageScaleMode.NO_SCALE;
                        
                        //获取场景
                        var stage3D:Stage3D = stage.stage3Ds[0];
                        
                        //侦听场景
                        stage3D.addEventListener(Event.CONTEXT3D_CREATE, initialize);
                        
                        //申请一个Context3D对象
                        stage3D.requestContext3D();
               
                        
                }
        
                private function initialize(e:Event):void
                {
                        var stage3D:Stage3D = e.target as Stage3D;

                        //获得3D场景
                        context3D = stage3D.context3D;
                        
                        //设置混色模式,正常的透明度
                        context3D.setBlendFactors(Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
                        
                        //创建重绘区域,消锯齿程度(0 2 4 8 16),是否具有深度缓存
                        context3D.configureBackBuffer(W, H, 2, false);
                        
                        //关闭错误提示
                        context3D.enableErrorChecking = false;
                        
                        //创建一个显示对象
                        sprite = new Sprite2D(context3D, resClass);
               
                        addEventListener(Event.ENTER_FRAME, renderFrame)

                }
        
                /**
                 * 渲染
                 * @param        e
                 */
                private function renderFrame(e:Event):void
                {
                        //清屏
                        context3D.clear(0, 0, 0, 0);
                        //重绘显示对象
                        sprite.paint();
                        //重绘屏幕
                        context3D.present();
                }
        }
}
Model2D.as
package
{
        
        import flash.display3D.Context3D;
        import flash.display3D.Context3DVertexBufferFormat;
        import flash.display3D.textures.Texture;
        import flash.display3D.VertexBuffer3D;
        import flash.geom.Matrix3D;
        import flash.geom.Vector3D;
        

        public class Model2D
        {
               
                /**
                 * 基本的控制属性
                 */
                public var x:Number=0;
                public var y:Number=0;
                public var z:Number=0;
                public var rotation:Number=0;
                public var width:Number=0;
                public var height:Number=0;
                public var scaleX:Number=1;
                public var scaleY:Number=1;

               
                //缓冲顶点数据
                private var buffer:VertexBuffer3D;
               
                //矩阵
                private var matrix:Matrix3D;
               
                public function Model2D(context:Context3D)
                {
                        //创建一个顶点缓冲4行4列
                        buffer     = context.createVertexBuffer(4, 4); //x, y, u, v
                        //创建一个试图矩阵
                        matrix     = new Matrix3D();
                        //上传顶点坐标从0开始,顶点元素数量为4
                        buffer.uploadFromVector(Vector.<Number>
                        ([
                                -1.0, 1.0, 0.0, 1.0,
                                -1.0,-1.0, 0.0, 0.0,
                                 1.0,-1.0, 1.0, 0.0,
                                 1.0, 1.0, 1.0, 1.0
                        ]), 0, 4);
                }
               
                /**
                 * 绘制
                 * @param        context
                 * @param        texture
                 */
                public function paint(context:Context3D, texture:Texture):void
                {
                        
                        //上传XY坐标属性对应va0,偏移量为0,长度为2
                        context.setVertexBufferAt(0, buffer, 0, Context3DVertexBufferFormat.FLOAT_2); //xy
                        
                        //上传UV坐标,对应va1,偏移量为2,长度为2
                        context.setVertexBufferAt(1, buffer, 2, Context3DVertexBufferFormat.FLOAT_2); //uv
                        
                        //上传纹理,对应fs0
                        context.setTextureAt(0, texture);

                }
               
                /**
                 * 获取已经处理好的matrix3D对象
                 * @return
                 */
                public function matrix3D():Matrix3D
                {
                        //重置矩阵
                        matrix.identity();
                        
                        //旋转
                        matrix.appendRotation(rotation, Vector3D.Z_AXIS);
                        
                        //缩放
                        matrix.appendScale(width * (scaleX / 2), height * (scaleY / 2), 1);
                        
                        //位置
                        matrix.appendTranslation((width / 2) + x, (height / 2) + y, z);
                        return matrix;
                }
        }
}
Sprite2D .as
package   
{
        

        import com.adobe.utils.AGALMiniAssembler;
        
        import flash.display.Bitmap;
        import flash.display.Sprite;
        import flash.display.Stage3D;
        import flash.display3D.Context3D;
        import flash.display3D.Context3DProgramType;
        import flash.display3D.Context3DTextureFormat;
        import flash.display3D.IndexBuffer3D;
        import flash.display3D.Program3D;
        import flash.display3D.textures.Texture;
        import flash.geom.Matrix3D;
        

        public class Sprite2D
        {
                private var W:Number = 1024;
                private var H:Number =768;
                private var sprite:Model2D;
                private var context3D:Context3D;
                private var texture:Texture;
                private var texture2:Texture;
                private var shaderProgramrogram3D;
                private var indexBuffer:IndexBuffer3D;
               
                //渲染矩阵
                private var spriteMatrix:Matrix3D = new Matrix3D();
               
                //视图矩阵
                private var viewMatrix:Matrix3D = new Matrix3D();
                public function Sprite2D(context3D:Context3D,resClss:Class):void
                {
                        this.context3D = context3D;
                        //着色器语言
                        var vertexShader:Array =
                        [
                            //矩阵相乘把3D矩阵转换为2D坐标输出给顶点着色器
                                "m44 op, va0, vc4",
                                
                                //移动UV信息到v0
                                "mov v0, va1"   
                        ];
                        
                        //汇编解释器
                        var vertexAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                        
                        //获得指定的解释器内容
                        vertexAssembler.assemble(flash.display3D.Context3DProgramType.VERTEX, vertexShader.join("\n"));
                        
                        //模糊灰度
                        var fragmentShader:Array =
                        [
                                
                                //取第一个采样点
                                "tex ft0, v0, fs0<2d,linear,nomip>",
                        
                                //先复制fc1参数列表里的值到零时寄存器ft2中,备用
                                "mov ft2,fc1",
                                //然后复制插值坐标到零时寄存器ft0中
                                "mov ft0,v0",
                                //然后除以一个分量,用于缩放
                                "div ft0,ft0,fc0.z",
                                //最后通过ft0获取当前像素信息
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                //然后除以一个分量
                                "mul ft1,ft1,fc0.wwww",
                                //最后把ft1的结果相加到ft2中
                                "add ft2,ft2,ft1",
                                
                                //移动UV到ft0中
                                "mov ft0,v0",
                                //取周围的像素,fc0.x=2像素,让当前的插值坐标加上2像素
                                "add ft0.x,v0.x,fc0.x",
                                //然后除以一个分量,用于缩放
                                "div ft0.x,ft0.x,fc0.z",
                                //最后获取处理过的插值坐标下的像素信息
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                //乘以一个分量,因为要取周围9个像素点的信息,所以得把每个信息都除以9降低饱和度
                                "mul ft1,ft1,fc0.wwww",
                                //醉后再累加,下面的原理同上,重复9个步骤
                                "add ft2,ft2,ft1",
                                
                                "mov ft0,v0",
                                "sub ft0.x,v0.x,fc0.x",
                                "div ft0.x,ft0.x,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                                
                                "mov ft0,v0",
                                "add ft0.y,v0.y,fc0.x",
                                "div ft0.y,ft0.y,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                                
                                "mov ft0,v0",
                                "sub ft0.y,v0.y,fc0.x",
                                "div ft0.y,ft0.y,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                                
                                
                                "mov ft0,v0",
                                "add ft0.x,v0.x,fc0.x",
                                "add ft0.y,v0.y,fc0.x",
                                "div ft0.x,ft0.x,fc0.z",
                                "div ft0.y,ft0.y,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                                
                                
                                "mov ft0,v0",
                                "sub ft0.x,v0.x,fc0.x",
                                "sub ft0.y,v0.y,fc0.x",
                                "div ft0.x,ft0.x,fc0.z",
                                "div ft0.y,ft0.y,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                                
                                "mov ft0,v0",
                                "add ft0.x,v0.x,fc0.x",
                                "sub ft0.y,v0.y,fc0.x",
                                "div ft0.x,ft0.x,fc0.z",
                                "div ft0.y,ft0.y,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                                
                                "mov ft0,v0",
                                "sub ft0.x,v0.x,fc0.x",
                                "add ft0.y,v0.y,fc0.x",
                                "div ft0.x,ft0.x,fc0.z",
                                "div ft0.y,ft0.y,fc0.z",
                                "tex ft1, ft0, fs0 <2d,linear,nomip>",
                                "mul ft1,ft1,fc0.wwww",
                                "add ft2,ft2,ft1",
                        
                                
                                //最后把累加到的ft2输出就形成了模糊效果
                                "mov oc, ft2"//输出到像素着色器
                        ];
                        

        
                        //汇编解释器
                        var fragmentAssembler:AGALMiniAssembler = new AGALMiniAssembler();
                        
                        //获得指定的解释器内容
                        fragmentAssembler.assemble(Context3DProgramType.FRAGMENT, fragmentShader.join("\n"));
                        
                        texture = initBitmap(resClss,Main.size);
                        
                        //获得场景的绘图指令
                        shaderProgram = context3D.createProgram();
                        
                        //刷新场景视图信息
                        shaderProgram.upload(vertexAssembler.agalcode, fragmentAssembler.agalcode);
                        
                        //创建一个节点缓冲区,四边形为6个,因为顶点信息为012,023
                        indexBuffer = context3D.createIndexBuffer(6);
               
                        //填充三角点信息,节点的起点和终点,节点的个数,正好构成四边形
                        indexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 0, 2, 3]), 0, 6);
                                       
                }
                private static function makeOrthoProjection(w:Number, h:Number, n:Number, f:Number):Matrix3D
                {
                        return new Matrix3D(Vector.<Number>
                                ([
                                        2/w, 0  ,       0,        0,
                                        0  , 2/h,       0,        0,
                                        0  , 0  , 1/(f-n), -n/(f-n),
                                        0  , 0  ,       0,        1
                                ]));
                }
               
                private function initBitmap(resClass:Class,w:int):Texture
                {        
                        //创建位图对象
                        var bitmap:Bitmap = new resClass();
                        //创建贴图缓冲区
                        var texture:Texture = context3D.createTexture(w,w, Context3DTextureFormat.BGRA, true);
                        //填充位图到贴图缓冲区
                        texture.uploadFromBitmapData(bitmap.bitmapData);
               
                        //创建显示对象,填入主场景
                        sprite = new Model2D(context3D);
                        //设置显示对象的场景和贴图缓冲区
                        return texture
                }
               
               
                public function paint():void
                {
               
                        sprite.width    = Main.size;
                        sprite.height   = Main.size;
                        
                        //重置
                        spriteMatrix.identity();
                        
                        //融合矩阵
                        spriteMatrix.append(sprite.matrix3D());
                        
                        //重置
                        viewMatrix.identity();
                        
                        //设置坐标
                        viewMatrix.appendTranslation( -W / 2, -H / 2, 0);
                        
                        //设置比例
                        viewMatrix.appendScale(1, 1, 1);
                        
                        //融合矩阵
                        spriteMatrix.append(viewMatrix);
                        
                        //融合矩阵
                        spriteMatrix.append(makeOrthoProjection(W, -H, 0, 1));
                        
                        //设置场景的绘图指令
                        context3D.setProgram(shaderProgram);
                        
                        //上传材质
                        sprite.paint(context3D, texture);
                        
                        //上传3D矩阵对应AGAL中的vc0
                        context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 4, spriteMatrix, true);
                        
                        //BOX模糊参数,2/Main.size代表偏移像素的位置,1代表缩放值,1/9代表分量
                        context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, Vector.<Number>([2/Main.size,2/ Main.size,1,1/9]) );
                        
                        //上传三角顶点索引,起点为0,画2个三角形
                        context3D.drawTriangles(indexBuffer, 0, 2);
                        
                        
                }
               
        }

}
下一节,将会对这个源码进行横向解析;



作者: ymwv101    时间: 2013-8-8 21:44
ding!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
作者: justinluberg    时间: 2013-8-13 13:18
非常不错的代码,这个是楼主自己写的? 膜拜高人!
作者: libufan    时间: 2013-8-14 10:25
非常不错的代码
作者: 89684598    时间: 2014-3-26 20:42
Thanks for sharing !




欢迎光临 纳金网 (http://c-www.narkii.com/club/) Powered by Discuz! X2.5