zoukankan      html  css  js  c++  java
  • 一个agal的高光实现代码

    package test
    {
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;

    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.Stage;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTextureFormat;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.display3D.textures.Texture;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.events.PressAndTapGestureEvent;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.geom.Vector3D;
    import flash.ui.Keyboard;

    public class TestAgal extends Sprite
    {
    [Embed(source="/assets/cloth.jpg")]
    private var cloth:Class;

    [Embed(source="/assets/skyBox.png")]
    private var skyBox:Class;

    [Embed(source="/assets/flower.jpg")]
    private var flower:Class;

    [Embed(source="/assets/trinket_diffuse.jpg")]
    private var trinketDiff:Class;

    [Embed(source="/assets/trinket_normal.jpg")]
    private var trinketNor:Class;

    [Embed(source="/assets/trinket_specular.jpg")]
    private var trinketSpe:Class;

    protected var context3D:Context3D;
    protected var program:Program3D;
    protected var vertexbuffer:VertexBuffer3D;
    protected var indexbuffer:IndexBuffer3D;

    private var texture:Texture;
    private var texture1:Texture;
    private var xR:Boolean = false;
    private var yR:Boolean = false;
    private var zR:Boolean = false;
    private var projectionTransform:PerspectiveMatrix3D;

    private var lightPos:Vector3D = new Vector3D(0,0,-10);

    private var lightStr:Number = 1;
    private var lightStrAdd:Number = -0.01;

    private var cameraMatrix:Matrix3D;
    private var objMatrix:Matrix3D = new Matrix3D();
    private var endMatrix:Matrix3D = new Matrix3D();

    private var aspect:Number;
    public function TestAgal(context3D:Context3D,stage:Stage)
    {
    this.context3D = context3D;
    stage.addEventListener(Event.ENTER_FRAME, onRender);
    stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown)
    stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
    aspect = stage.width/stage.height;
    initProjection();
    initMolehill();
    }
    protected function initProjection():void
    {
    aspect = 4/3;
    var zNear:Number = 0.1;
    var zFar:Number = 1000;
    var fov:Number = 45*Math.PI/180;


    cameraMatrix = new Matrix3D();
    cameraMatrix.appendTranslation(0,0,-5);
    // cameraMatrix.invert();

    projectionTransform = new PerspectiveMatrix3D();
    projectionTransform.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
    // projectionTransform.perspectiveFieldOfViewRH(45, aspect, zNear, zFar);
    // projectionTransform.prepend(cameraMatrix);
    }

    protected function initMolehill():void
    {
    var w:Number = 2;
    var h:Number = 3;
    var hw:Number = w * .5;
    var hh:Number = h * .5;
    var vertices:Vector.<Number> = Vector.<Number>([
    -hw,-hh,0, 0,1, 0,0,-1,//顶点 UV 法线 3+2+3=8
    hw,-hh,0, 1,1, 0,0,-1,
    hw,hh, 0, 1,0, 0,0,-1,
    -hw,hh,0, 0,0, 0,0,-1
    ]);

    var offset:int = 8;
    vertexbuffer = context3D.createVertexBuffer(vertices.length/offset, offset);
    vertexbuffer.uploadFromVector(vertices, 0, vertices.length/offset);
    var indices:Vector.<uint> = Vector.<uint>([0,1,3,1,2,3]);

    indexbuffer = context3D.createIndexBuffer(indices.length);
    indexbuffer.uploadFromVector (indices, 0, indices.length);

    var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
    vertexShaderAssembler.assemble( Context3DProgramType.VERTEX,
    "m44 op va0 vc0 "+ //顶点
    "mov v1 va1 "+ //UV
    "mov v2 va2"//法线
    );
    var fragmentShaderAssembler : AGALMiniAssembler= new AGALMiniAssembler();
    fragmentShaderAssembler.assemble( Context3DProgramType.FRAGMENT,
    "tex ft0,v1,fs0<2d,linear,repeat> " +
    "mov ft1 fc0 " +
    "mov ft2 v2 " +
    "m44 ft2 ft2 fc3 " +
    "dp3 ft3.w ft1 ft2 " + //ft3 = cos涩塔
    "abs ft3.w ft3.w " +
    "mul ft4 ft0 ft3.wwww "+
    "mul ft4 ft4 fc1.wwww "+

    "dp3 ft6.w fc2 ft2 " +
    "abs ft6.w ft6.w " +
    "mul ft7 fc4 ft6.wwww " +

    "add ft0 ft0 ft4 " + // 原始颜色 += 漫反射光照加成颜色
    "add ft0 ft0 ft7 " + // 原始颜色 += 高光加成颜色
    // "add ft0 ft0 fc1 " + // 叠加一个环境光颜色

    "mov oc,ft0"
    );

    var bitmap:Bitmap = new trinketDiff();
    texture = context3D.createTexture(bitmap.width,bitmap.height,Context3DTextureFormat.BGRA,false);
    texture.uploadFromBitmapData(bitmap.bitmapData);

    var bitmap1:Bitmap = new trinketNor();
    texture1 = context3D.createTexture(bitmap1.width,bitmap1.height,Context3DTextureFormat.BGRA,false);
    texture1.uploadFromBitmapData(bitmap1.bitmapData);

    program = context3D.createProgram();
    program.upload( vertexShaderAssembler.agalcode, fragmentShaderAssembler.agalcode);
    }

    private function culculateNormal(vecVb:Vector.<Number>,vertexNum:int):void
    {
    var data32PerVertex:int = vecVb.length/vertexNum;
    var vertexArr:Array = [];
    for (var i:int=0;i<vertexNum;i++){
    var x:Number = vecVb[data32PerVertex*i];
    var y:Number = vecVb[data32PerVertex*i+1];
    var z:Number = vecVb[data32PerVertex*i+2];
    vertexArr.push(new Vector3D(x,y,z));
    }

    var calcNormal:Function = function(p1:Vector3D,p2:Vector3D,p3:Vector3D):Vector3D{
    var source2:Vector3D = new Vector3D(p2.x-p1.x,p2.y-p1.y,p2.z-p1.z);
    var source1:Vector3D = new Vector3D(p3.x-p1.x,p3.y-p1.y,p3.z-p1.z);
    var norV:Vector3D = new Vector3D();
    norV.x = source1.y * source2.z - source1.z * source2.y;
    norV.y = source1.z * source2.x - source1.x * source2.z;
    norV.z = source1.x * source2.y - source1.y * source2.x;
    norV.normalize();
    return norV;
    }

    var calcNormalAvg:Function = function(arr:Array,offsetNormal:int):void{
    var sideLen:int = arr.length/3;
    var sideAvg:Vector3D = new Vector3D();
    for (var i:int=0;i<sideLen;i++){
    var side:Vector3D = calcNormal(vertexArr[arr[i*3]],vertexArr[arr[i*3+1]],vertexArr[arr[i*3+2]]);
    sideAvg=sideAvg.add(side);
    }
    sideAvg.x = sideAvg.x/sideLen;
    sideAvg.y = sideAvg.y/sideLen;
    sideAvg.z = sideAvg.z/sideLen;
    sideAvg.normalize();
    vecVb[offsetNormal] = -sideAvg.x;
    vecVb[offsetNormal+1] = -sideAvg.y;
    vecVb[offsetNormal+2] = -sideAvg.z;
    }
    // calcNormalAvg([0,1,3,1,2,3],vertexNum*data32PerVertex)
    }

    protected function onRender(e:Event):void
    {
    if ( !context3D ) return;

    if(xR) objMatrix.appendRotation(1,Vector3D.X_AXIS);
    if(yR) objMatrix.appendRotation(1,Vector3D.Y_AXIS);
    if(zR) objMatrix.appendRotation(1,Vector3D.Z_AXIS);

    endMatrix.identity();
    endMatrix.append(objMatrix);
    var viewMatrix:Matrix3D = cameraMatrix.clone();
    viewMatrix.invert();
    viewMatrix.append(projectionTransform);
    endMatrix.append(viewMatrix);

    // endMatrix.copyFrom(objMatrix);
    // endMatrix.append(projectionTransform);

    context3D.setVertexBufferAt (0, vertexbuffer, 0, Context3DVertexBufferFormat.FLOAT_3);//顶点 Va0
    context3D.setVertexBufferAt(1, vertexbuffer, 3, Context3DVertexBufferFormat.FLOAT_2);// uv Va1
    context3D.setVertexBufferAt(2,vertexbuffer,5,Context3DVertexBufferFormat.FLOAT_3); // 法线 Va2
    var light:Vector3D=lightPos.clone(); // 不含平移元素的变换
    light.normalize();
    context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,0,Vector.<Number>([light.x,light.y,light.z,0]));

    // -- 设置状态机当前的fc1 静态常量:xyz用于 环境光颜色叠加 W用于漫反射光照强度 这里叠加一个红色环境光
    var ambientR:Number = 1//lightStr*0.2;
    var ambientG:Number = 0//(1-lightStr)*0.2;
    var ambientB:Number = 0//(lightStr/2)*0.2;
    context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,1,Vector.<Number>([ambientR,ambientG,ambientB,lightStr]));//lightStr

    var halfEyeLightPos:Vector3D = cameraMatrix.position.clone();
    halfEyeLightPos=halfEyeLightPos.add(lightPos);

    halfEyeLightPos.x/=2;
    halfEyeLightPos.y/=2;
    halfEyeLightPos.z/=2;
    halfEyeLightPos.normalize();
    context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,2,Vector.<Number>([halfEyeLightPos.x,halfEyeLightPos.y,halfEyeLightPos.z,0]));
    // -- 设置状态机当前的fc3 静态常量:用于将模型矩阵变换传入
    context3D.setProgramConstantsFromMatrix(Context3DProgramType.FRAGMENT,3,objMatrix);
    // -- 设置状态机当前的fc4 静态常量:高光颜色
    var specularR:Number = 0//lightStr*0.3;
    var specularG:Number = 1//lightStr*0.3;
    var specularB:Number = 0//lightStr*0.3;
    context3D.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT,4,Vector.<Number>([specularR,specularG,specularB,0]));

    context3D.setTextureAt(0,texture);
    // context3D.setTextureAt(1,texture1);
    context3D.setProgram(program);

    context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, endMatrix, true);

    context3D.clear();
    context3D.drawTriangles(indexbuffer);
    context3D.present();
    }
    /**
    * 当鼠标移动的时候记录的鼠标点
    */
    private var onMouseDownPt:Point = new Point();
    /**
    * 鼠标移动旋转物体
    * 原理无非就是根据每次移动时的像素差距来计算让物体矩阵M在当前的状态下再围绕X和Y旋转(至于围绕Z轴旋转可以自己添加试试)
    * @param e
    *
    */
    private function onMouseDown(e:MouseEvent):void{
    onMouseDownPt.x = e.stageX;
    onMouseDownPt.y = e.stageY;
    stage.addEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
    stage.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
    }
    private function onMouseMove(e:MouseEvent):void{
    var dx:Number = e.stageX - onMouseDownPt.x;
    var dy:Number = e.stageY - onMouseDownPt.y;
    var degreesY:Number = -dx/2;
    var degreesX:Number = -dy/2;
    onMouseDownPt.x = e.stageX;
    onMouseDownPt.y = e.stageY;
    objMatrix.appendRotation(degreesY,Vector3D.Y_AXIS);
    objMatrix.appendRotation(degreesX,Vector3D.X_AXIS);
    }
    private function onMouseUp(e:MouseEvent):void{
    stage.removeEventListener(MouseEvent.MOUSE_MOVE,onMouseMove);
    stage.removeEventListener(MouseEvent.MOUSE_UP,onMouseUp);
    }

    private var moveDis:Number = 0.1;
    protected function onKeyDown(event:KeyboardEvent):void
    {
    switch(event.keyCode)
    {
    case Keyboard.X:
    xR = !xR;
    break;
    case Keyboard.C:
    yR = !yR;
    break;
    case Keyboard.Z:
    zR = !zR;
    break;
    case Keyboard.R:
    objMatrix.identity();
    xR = false;
    yR = false;
    zR = false;
    break;
    case Keyboard.LEFT:
    lightPos.x -= moveDis;
    break;
    case Keyboard.RIGHT:
    lightPos.x += moveDis;
    break;
    case Keyboard.UP:
    lightPos.y += moveDis;
    break;
    case Keyboard.DOWN:
    lightPos.y -= moveDis;
    break;
    case Keyboard.A:
    cameraMatrix.appendTranslation(moveDis,0,0);
    break;
    case Keyboard.D:
    cameraMatrix.appendTranslation(-moveDis,0,0);
    break;
    case Keyboard.W:
    cameraMatrix.appendTranslation(0,-moveDis,0);
    break;
    case Keyboard.S:
    cameraMatrix.appendTranslation(0,moveDis,0);
    break;
    }
    trace("lightPos:"+lightPos);
    trace("cameraPos"+cameraMatrix.decompose())
    }
    /**
    * 判断设备丢失
    *
    */
    private function get isContextDispose():Boolean{
    return context3D==null||context3D.driverInfo=="Disposed"||context3D.driverInfo=="";
    }
    }
    }

  • 相关阅读:
    redhat,centos Linux常用命令LS之常用功能
    人生信用卡
    如何让Redhat Linux启动时进入字符终端模式(不进入XWindow)
    OpenJDK和JDK区别
    Linux rpm 命令参数使用详解[介绍和应用]
    linux 的vim命令详解
    centos6.4安装javajdk1.8
    samba服务器 实现Linux与windows 文件共享
    SELinux 宽容模式(permissive) 强制模式(enforcing) 关闭(disabled) 几种模式之间的转换
    linux学习之 Linux下的Eclipse安装
  • 原文地址:https://www.cnblogs.com/Star9527/p/6719190.html
Copyright © 2011-2022 走看看