2011-10-13 9 views
2

내가 AGAL이 Stage3D 객체에 텍스처/비트 맵을 렌더링하기 위해 작성하는 몇 가지 내용은 다음 웹 사이트를 살펴 보았다 :2D 공간에서 Stage3D에 텍스처 (BitmapData)를 렌더링하는 데 필요한 저수준 코드는 무엇입니까?

http://iflash3d.com/shaders/my-name-is-agal-i-come-from-adobe-1/

하지만 3D 공간에서 객체를 생성하는 방법에 대해 자세히 다루 보인다. 어쩌면 피할 수없는 것일까 요?

하지만 어쨌든이 요청할 것 :

은 무엇 것이다 베어 뼈 필요한 AGAL 코드 & AS3 코드를 Stage3D 여러 스프라이트를 렌더링하기 위해 작성하는?

참고 : 위치, 크기 및 회전 변환 만 필터, 효과 또는 쉐이더가 필요하지 않습니다. 또한이 작업을 수행하는 기존 타사 API를 찾고 있지 않습니다. 이 저수준 언어를 직접 실험하고 싶습니다.

답변

7

이것은 모두 기사에 설명되어 있으며, '2d'가되도록 직각 투영 행렬을 만드는 것이 누락되었습니다.

var projection:Matrix3D = new Matrix3D(Vector.<Number>([ 
    2/(viewPort.right - viewPort.left), 0, 0, 0, 
    0, 2/(viewPort.top - viewPort.bottom), 0, 0, 
    0, 0, 1/(far - near), 0, 
    0, 0, near/(near - far), 1 
])); 

일반적인 추상화 및 최적화는 스프라이트 배치 처리입니다. 다음 예제는 기능이 완료되지 않았지만 색조, 정렬, 회전 및 오프셋은 현재 구현되지 않았지만 그렇게하는 것은 쉽지 않습니다.

package 
{ 
    import com.adobe.utils.*; 

    import flash.display3D.*; 
    import flash.display3D.textures.*; 
    import flash.geom.*; 
    import flash.system.System; 
    import flash.utils.*; 

    public class SpriteBatch3D 
    { 
     private static const SPRITES_PER_BATCH:int = 2048; 
     private static const DATA_PER_VERTEX:int = 4; 

     private var _context3D:Context3D; 

     private var _vertexBuffer:VertexBuffer3D; 
     private var _indexBuffer:IndexBuffer3D; 
     private var _program:Program3D; 
     private var _matrix3D:Matrix3D; 
     private var _numSprites:Number; 
     private var _sprites:Vector.<SpriteBatch3DSprite>; 

     public function SpriteBatch3D(context3D:Context3D) 
     { 
      if (context3D == null) { 
       throw new ArgumentError("context3D cannot be null."); 
      } 

      _context3D = context3D; 
      allocateBuffers(); 
      allocateShaders(); 
      allocateSprites(); 
     } 

     private function allocateSprites():void { 
      _sprites = createSprites(); 
      _numSprites = 0; 
     } 

     private function createSprites():Vector.<SpriteBatch3DSprite> { 
      var sprites:Vector.<SpriteBatch3DSprite> = new Vector.<SpriteBatch3DSprite>(SPRITES_PER_BATCH); 

      for (var i:int = 0; i < sprites.length; i++) 
      { 
       sprites[i] = new SpriteBatch3DSprite; 
      } 

      return sprites; 
     } 

     private function allocateShaders():void 
     { 
      var vertexAssembler:AGALMiniAssembler = new AGALMiniAssembler(); 
      vertexAssembler.assemble(flash.display3D.Context3DProgramType.VERTEX, 
       "m44 op, va0, vc0 \n" + 
       "mov v0, va1  \n" 
      ); 

      var fragmentAssembler:AGALMiniAssembler = new AGALMiniAssembler(); 
      fragmentAssembler.assemble(flash.display3D.Context3DProgramType.FRAGMENT, 
       "tex ft1, v0, fs0 <2d,linear> \n" + 
       "mov oc, ft1" 
      ); 

      _program = _context3D.createProgram(); 
      _program.upload(vertexAssembler.agalcode, fragmentAssembler.agalcode); 
     } 

     private function allocateBuffers():void 
     { 
      _vertexBuffer = _context3D.createVertexBuffer(SPRITES_PER_BATCH * 4, DATA_PER_VERTEX); 
      _vertexBuffer.uploadFromByteArray(createVertexData(), 0, 0, SPRITES_PER_BATCH * 4); 

      _indexBuffer = _context3D.createIndexBuffer(SPRITES_PER_BATCH * 6); 
      _indexBuffer.uploadFromByteArray(createIndexData(), 0, 0, SPRITES_PER_BATCH * 6); 
     } 

     private function createVertexData():ByteArray 
     { 
      var data:ByteArray = new ByteArray; 
      data.length = SPRITES_PER_BATCH * 4 * (4 * DATA_PER_VERTEX); 
      data.endian = Endian.LITTLE_ENDIAN; 

      return data; 

     } 
     private function createIndexData():ByteArray { 

      var data:ByteArray = new ByteArray(); 
      data.endian = Endian.LITTLE_ENDIAN; 
      data.length = (SPRITES_PER_BATCH * 6) * 2; 

      for (var i:int = 0; i < SPRITES_PER_BATCH * 6; i++) 
      { 
       data.writeShort(i * 4); 
       data.writeShort(i * 4 + 1); 
       data.writeShort(i * 4 + 2); 

       data.writeShort(i * 4); 
       data.writeShort(i * 4 + 2); 
       data.writeShort(i * 4 + 3); 
      } 

      return data; 
     } 

     public function dispose():void { 
      if (_vertexBuffer) { 
       _vertexBuffer.dispose(); 
       _vertexBuffer = null; 
      } 

      if (_indexBuffer) { 
       _indexBuffer.dispose(); 
       _indexBuffer = null; 
      } 
     } 

     public function begin(matrix3D:Matrix3D):void { 
      _matrix3D = matrix3D; 
     } 

     public function draw(texture:Texture, destination:Rectangle, source:Rectangle=null, origin:Point=null, color:int=0xFFFFFF, rotation:Number=0, depth:Number=0):void { 
      if (source == null) { 
       source = new Rectangle(0, 0, 1, 1); 
      } 

      if (origin == null) { 
       origin = new Point(0, 0); 
      } 

      if (_sprites.length == _numSprites) { 
       _sprites = _sprites.concat(createSprites());     
      } 

      _sprites[_numSprites].texture  = texture; 
      _sprites[_numSprites].destination = destination; 
      _sprites[_numSprites].source  = source; 
      _sprites[_numSprites].origin  = origin; 
      _sprites[_numSprites].rotation  = rotation; 
      _sprites[_numSprites].depth   = depth; 

      _numSprites++;   
     } 

     public function end():void {  
      _context3D.setProgram(_program); 
      _context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, _matrix3D, true); 

      _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_2); // x, y 
      _context3D.setVertexBufferAt(1, _vertexBuffer, 2, Context3DVertexBufferFormat.FLOAT_2); // u, v 

      _context3D.setCulling(Context3DTriangleFace.FRONT); 
      _context3D.setDepthTest(false, Context3DCompareMode.ALWAYS); 

      // TODO sorting. 
      var sprites:Vector.<SpriteBatch3DSprite> = _sprites; 
      var texture:Texture = null; 
      var firstIndex:int = 0; 

      for (var index:int = 0; index < _numSprites; index++) { 
       if (texture != sprites[index].texture) { 
        if (index > firstIndex) { 
         renderBatch(texture, sprites, firstIndex, index - firstIndex); 
         firstIndex = index; 
        } 

        texture = sprites[index].texture; 
       } 
      } 

      renderBatch(texture, sprites, firstIndex, _numSprites - firstIndex); 
      _numSprites = 0; 
     } 

     private function renderBatch(texture:Texture, sprites:Vector.<SpriteBatch3DSprite>, offset:int, count:int):void { 
      if (_numSprites == 0) { 
       return; 
      } 

      while(count > 0) { 
       var data:ByteArray = new ByteArray; 
       data.endian = Endian.LITTLE_ENDIAN; 

       var size:int = count; 
       if (size > SPRITES_PER_BATCH) { 
        size = Math.min(sprites.length, SPRITES_PER_BATCH); 
       } 

       for (var i:int = offset; i < (offset + size); i++) { 
        data.writeFloat(sprites[i].destination.left); 
        data.writeFloat(sprites[i].destination.top); 
        data.writeFloat(sprites[i].source.left); 
        data.writeFloat(sprites[i].source.top); 

        data.writeFloat(sprites[i].destination.left); 
        data.writeFloat(sprites[i].destination.bottom); 
        data.writeFloat(sprites[i].source.left); 
        data.writeFloat(sprites[i].source.bottom); 

        data.writeFloat(sprites[i].destination.right); 
        data.writeFloat(sprites[i].destination.bottom); 
        data.writeFloat(sprites[i].source.right); 
        data.writeFloat(sprites[i].source.bottom); 

        data.writeFloat(sprites[i].destination.right); 
        data.writeFloat(sprites[i].destination.top); 
        data.writeFloat(sprites[i].source.right); 
        data.writeFloat(sprites[i].source.top); 
       } 

       _vertexBuffer.uploadFromByteArray(data, 0, 0, size * 4);    
       _context3D.setTextureAt(0, texture); 
       _context3D.drawTriangles(_indexBuffer, 0, size * 2); 

       offset += size; 
       count -= size; 
      } 
     } 
    } 
} 

import flash.display3D.textures.*; 
import flash.geom.*; 

internal class SpriteBatch3DSprite { 
    public var texture:Texture; 
    public var source:Rectangle; 
    public var destination:Rectangle; 
    public var origin:Point; 
    public var rotation:Number; 
    public var depth:Number; 
} 

사용

batch.begin(matrix); 
batch.draw(texture1, new Rectangle(100, 0, 100, 100)); 
batch.draw(texture2, new Rectangle(0, 200, 100, 100)); 
batch.draw(texture3, new Rectangle(0, 500, 100, 100)); 
batch.draw(texture4, new Rectangle(900, 0, 100, 100)); 
batch.end(); 

일부 사소한주의 텍스처 개체를 사용하면 텍셀 공간에서 소스 사각형 다루고있는 폭이나 높이 게터 (0 ~ 1)를 수행하지 않기 때문에, 그러나이있다

또한 Context3D는 뷰포트에 대한 정보를 전달하지 않으므로 매트릭스를 내부적으로 구성 할 수 없으며 종속성으로 해결되어야합니다.