Render Sessions

By default, each mesh element is drawn to a single Render Session object. The default Render Session object used by the view and the scene is represented by the SpriteSession class. Because each 3D object will share its parent's Render Session by default, this also means that each 3D object also uses the scene's SpriteSession object as well.

Away3D also includes a BitmapSession class, which provides easy access to the underlying bitmap data used to draw the Render Session to the screen. This bitmap data can be accessed and modified to create some interesting effects.

Postprocessing with the BitmapRenderSession

To demonstrate the use of the BitmapSession class, we will create an application where we replace the default SpriteSession object used by the view with a new BitmapSession object. Since we can get access to the BitmapData object used by the BitmapSession class to display the final result, we can use the various drawing routines provided by the BitmapData class to create some interesting effects.

The PostProcessingDemo application shown below will use the following process to create a smoky effect that appears to rise off the 3D objects in the scene:

  1. A copy of the last frame is transferred to a buffer.
  2. The buffer is translated slightly up along the Y-axis.
  3. The color of the pixels in the buffer are modified to be slightly more transparent, and to fade into a blue-gray color.
  4. The new frame is rendered.
  5. The new frame is drawn on top of the buffer.
  6. The buffer is drawn to the screen.
  7. Go back to step 1.
    package
    {
      import away3d.containers.ObjectContainer3D;
      import away3d.core.base.Mesh;
      import away3d.core.session.BitmapSession;
      import away3d.core.utils.Cast;
      import away3d.events.ViewEvent;
      import away3d.loaders.Max3DS;
      import away3d.materials.BitmapMaterial;
      import flash.display.BitmapData;
      import flash.events.Event;
      import flash.filters.BitmapFilterQuality;
      import flash.filters.BlurFilter;
      import flash.geom.ColorTransform;
      import flash.geom.Matrix;
      import flash.geom.Point;
    
      public class PostProcessingDemo extends Away3DTemplate
      {
        [Embed(source="ship.3ds", mimeType="application/octet-stream")] 
        protected var ShipModel:Class;
        [Embed(source="ship.jpg")] 
        protected var ShipTexture:Class;
    
        protected var shipModel:ObjectContainer3D;

The effect relies on the image from the last frame being carried across between frames to be used as the background for the next frame. The buffer variable will be used to reference the BitmapData object that contains the processed copy of the last frame.

    protected var buffer:BitmapData;

To use the BitmapSession class, we need to create a new instance of it. The BitmapSession constructor takes a single parameter that defines the scale. We have supplied a value of 1, which means that the BitmapSession uses the same resolution as the view.

    protected var bitmapSession:BitmapSession = 
      new BitmapSession(1);

The smoke effect will be smoothed using an instance of the BlurFilter class.

    protected var blur:BlurFilter = new BlurFilter();

The ColorTransform class can be used to modify the color and transparency of the individual pixels that make up an image. The following ColorTransform object will increase the transparency of a color (or, more accurately, make the color less opaque) while adding 1 to the red channel, 3 to the green channel, and 10 to the blue channel. Modifying the color channels in this way will eventually result in a blue-gray color.

    protected var fade:ColorTransform = 
      new ColorTransform(1, 1, 1, .99, 1, 3, 10, 0);

A number of the drawing routines used below require a Point object set to (0, 0). It is always best to try and avoid creating new objects where possible, so we define a new instance of the Point class here. If no parameters are specified for the Point constructor it will default to the position (0, 0).

    protected var point:Point = new Point();

For each frame, the pixels from the last frame will be translated up the screen. Note that we are working with the Flash 2D coordinate system here. This means that moving pixels up the screen involves decreasing their Y coordinates. The following matrix constructor specifies the default values for all the parameters except the sixth, which defines the translation along the Y-axis.

    protected var matrix:Matrix = new Matrix(1, 0, 0, 1, 0, -1);

    public function PostProcessingDemo()
    {
      super();
    }

    protected override function initEngine():void
    {
      super.initEngine();	

For the BitmapSession object we created to be used by the view, it has to be assigned to the View3D session property.

      view.session = bitmapRenderSession;
    }

    protected override function initScene():void
    {
      super.initScene();
      this.camera.z = 0;
      var shipMaterial:BitmapMaterial = 
        new BitmapMaterial(Cast.bitmap(ShipTexture));
      shipModel = Max3DS.parse(Cast.bytearray(ShipModel),
        {
          autoLoadTextures: false,
          scale: 0.2,
          z: 500
        }
      );
      for each (var child:Mesh in shipModel.children)
        child.material = shipMaterial;
      scene.addChild(shipModel);
    }

    protected override function initListeners():void
    {
      super.initListeners();

The second half of the effect is processed once the current frame has been rendered (that is, after the onEnterFrame() function has been called). For this, we register the onRenderComplete() function to be called when the ViewEvent.RENDER_COMPLETE event is dispatched. We could also have achieved the same result by performing the postprocessing once we had called the Away3DTemplate onEnterFrame() function (by calling super.onEnterFrame())

      view.addEventListener(
        ViewEvent.RENDER_COMPLETE, 
        onRenderComplete
      );
    }

    override protected function onEnterFrame(event:Event):void 
    {

The first half of the effect is processed before the current frame is rendered. Normally in the onEnterFrame() function, we start by immediately calling the onEnterFrame() function from the base class. In this case though we want to get access to the last frame that was rendered before the view clears the screen and renders the next frame. So we don't call super.onEnterFrame(event) right away.

We start by rotating the 3D object in the scene.

      shipModel.rotationX += 2;
      shipModel.rotationY += 1;

The first half of the effect involves taking the bitmap data from the last frame and drawing it to a buffer using a slight vertical offset and color transformation.

We need to get a copy of the bitmap data from the last frame rendered. This is done using the BitmapSession.getBitmapData() function, which takes the current view object as a parameter.

      var bitmapSessionData:BitmapData = 
        bitmapSession.getBitmapData(view);

If this is the first time a frame has been rendered (that is, buffer is null), the buffer is created to be the same size as the BitmapSession bitmap data by supplying bitmapSessionData.width and bitmapSessionData.height as the first two parameters of the BitmapData constructor.

      if (buffer == null)
      {
        buffer = new BitmapData(
          bitmapSessionData.width, 
          bitmapSessionData.height, 
          true, 
          0);
      }

The buffer content is cleared by drawing a blank rectangle over the buffer.

      buffer.fillRect(buffer.rect, 0);

The contents of the current frame is copied to the buffer using the BitmapData draw() function.

The first parameter, source, is the data source to copy from, which is set to the BitmapData object we retrieved from the BitmapSession and assigned to the bitmapSessionData variable.

The second parameter, matrix, is a matrix that can be used to transform the source data as it is copied. The matrix object supplied here translates the individual pixels up the screen by one.

The third parameter, colorTransform, is a ColorTransform object. The fade variable references a ColorTransform object that will convert the pixels to a blue color and decrease their alpha component, which has the effect of making them more transparent.

      buffer.draw(bitmapSessionData, matrix, fade);

Finally, we use the BlurFilter object, referenced by the blur variable, to apply a blur effect to the buffer. This is done using the BitmapData applyFilter() function.

The first parameter, sourceBitmapData, is the bitmap data source to apply the effect to. We have supplied the buffer itself.

The second parameter, sourceRect, defines the area within the bitmap data source to use as the input. We want to apply the effect to the whole image, so we supply the buffers rect property.

The third parameter, destPoint, defines the point within the destination image that corresponds to the upper-left corner of the source rectangle. This will always be the point (0, 0). For this we use the default Point object we created earlier.

The fourth parameter, filter, defines the filter object that you use to perform the filtering operation. We have supplied the previously created BlurFilter object referenced by the blur variable.

      buffer.applyFilter(buffer, buffer.rect, point, blur);

Now that we have captured and modified the last frame, we can go on to render the next frame.

      super.onEnterFrame(event);
    }

The second half of the effect is processed once the current frame has been rendered.

    protected function onRenderComplete(event:ViewEvent):void
    {

Once again we need to get a reference to the bitmap data of the BitmapSession object.

      var bitmapSessionData:BitmapData = 
        bitmapSession.getBitmapData(view);

This bitmap data is copied, or cloned, into a new BitmapData object that is assigned to the postProcess variable.

      var postProcess:BitmapData = bitmapSessionData.clone();

The current frame is drawn on top of the processed copy of the last frame.

      buffer.draw(postProcess);

This combined image is then drawn back into the BitmapSession, causing it to be drawn onto the screen.

      bitmapSessionData.copyPixels(buffer, buffer.rect, point);
    }
  }
}

The following image shows the final effect:

Postprocessing with the BitmapRenderSession
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.192.151