Search code examples
actionscript-3flashstage3dagal

Proper way to apply translation to vertices


I have the simple vertex shader:

m44 op, va0, vc0 
mov v0, va1

and the fragment shader:

mov oc, v0

I pass this vertices to it:

  x     y   z  w  r  g  b
-0.3, -0.3, 0, 1, 1, 0, 0,
 0,    0.3, 0, 1, 0, 1, 0,
 0.3, -0.3, 0, 1, 0, 0, 1

The result triangle looks like I expected. Now I want to apply some translation to the result triangle. I have declared a matrix, call appendTranslation(0.2, 0, 0) and pass it to the vertex shader. The problem is that the triangle remained in the same position but with different vertices position. It looks like this:

Bad triangle

Why I got this result, and what is the proper way to apply translation to vertices?

Here is full code of my program:

package tests 
{
    import com.adobe.utils.AGALMiniAssembler;
    import flash.display.Sprite;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DRenderMode;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.utils.ByteArray;

    [swf(width="500", height="500")]
    public class Stage3dTest extends Sprite
    {
        private var _context:Context3D;
        private var _vertexBuffer:VertexBuffer3D;
        private var _indexBuffer:IndexBuffer3D;
        private var _program:Program3D;
        private var _mat:Matrix3D;

        public function Stage3dTest() {
            if (stage) {
                onAddedToStage();
            } else {
                addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
            }
        }
        private function onAddedToStage(event:Event = null):void {
            this.stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onStage3dContext3DCreate);
            this.stage.stage3Ds[0].requestContext3D(Context3DRenderMode.SOFTWARE);
        }
        private function onStage3dContext3DCreate(event:Event):void {
            _mat = new Matrix3D();
            _mat.appendTranslation(0.2, 0, 0);
            _context = this.stage.stage3Ds[0].context3D;
            _context.configureBackBuffer(500, 500, 0, false);
            _vertexBuffer = _context.createVertexBuffer(3, 7);
            _indexBuffer = _context.createIndexBuffer(3);
            var p:Number = 0.3;
            var vertexData:Vector.<Number> = new <Number>[
                -p, -p, 0, 1, 1, 0, 0,
                0,   p, 0, 1, 0, 1, 0,
                p,  -p, 0, 1, 0, 0, 1
            ];
            _vertexBuffer.uploadFromVector(vertexData, 0, 3);
            _indexBuffer.uploadFromVector(new <uint>[0, 1, 2], 0, 3);
            createAndCompileProgram();
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
        }
        private function createAndCompileProgram():void {
            _program = _context.createProgram();
            var assembler:AGALMiniAssembler = new AGALMiniAssembler();
            var code:String = "";
            code += "m44 op, va0, vc0\n"+
                    "mov v0, va1\n";
            var vertexShader:ByteArray = assembler.assemble(Context3DProgramType.VERTEX, code);
            code = "mov oc, v0\n";
            var fragmentShader:ByteArray = assembler.assemble(Context3DProgramType.FRAGMENT, code);
            _program.upload(vertexShader, fragmentShader);
        }
        private function onEnterFrame(event:Event):void {
            _context.clear(0.9, 0.9, 0.9, 1);
            _context.setProgram(_program);
            _context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, _mat);
            _context.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_4);
            _context.setVertexBufferAt(1, _vertexBuffer, 4, Context3DVertexBufferFormat.FLOAT_3);
            _context.drawTriangles(_indexBuffer);
            _context.present();
        }
    }
}

Solution

  • You need to transpose a matrix. You can do it manually or you can pass a parameter here:

    _context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, _mat, true);