Ejemplo n.º 1
0
void ImposterCapture::_separateAlpha( GBitmap *imposterOut )
{
   PROFILE_START(TSShapeInstance_snapshot_sb_separate);

   // TODO: Remove all this when we get rid of the 'render on black/white'.

      // now separate the color and alpha channels
      GBitmap *bmp = new GBitmap;
      bmp->allocateBitmap(mDim, mDim, false, GFXFormatR8G8B8A8);
      U8 * wbmp = (U8*)mWhiteBmp->getBits(0);
      U8 * bbmp = (U8*)mBlackBmp->getBits(0);
      U8 * dst  = (U8*)bmp->getBits(0);

      const U32 pixCount = mDim * mDim;

      // simpler, probably faster...
      for ( U32 i=0; i < pixCount; i++ )
      {
         // Shape on black background is alpha * color, shape on white 
         // background is alpha * color + (1-alpha) * 255 we want 255 *
         // alpha, or 255 - (white - black).
         //
         // JMQ: or more verbosely:
         //  cB = alpha * color + (0 * (1 - alpha))
         //  cB = alpha * color
         //  cW = alpha * color + (255 * (1 - alpha))
         //  cW = cB + (255 * (1 - alpha))
         // solving for alpha
         //  cW - cB = 255 * (1 - alpha)
         //  (cW - cB)/255 = (1 - alpha)
         //  alpha = 1 - (cW - cB)/255
         // since we want alpha*255, multiply through by 255
         //  alpha * 255 = 255 - cW - cB
         U32 alpha = 255 - (wbmp[i*3+0] - bbmp[i*3+0]);
         alpha    += 255 - (wbmp[i*3+1] - bbmp[i*3+1]);
         alpha    += 255 - (wbmp[i*3+2] - bbmp[i*3+2]);

         if ( alpha != 0 )
         {
            F32 floatAlpha = ((F32)alpha)/(3.0f*255.0f); 
            dst[i*4+0] = (U8)(bbmp[i*3+0] / floatAlpha);
            dst[i*4+1] = (U8)(bbmp[i*3+1] / floatAlpha);
            dst[i*4+2] = (U8)(bbmp[i*3+2] / floatAlpha);

            // Before we assign the alpha we "fizzle" the value
            // if its greater than 84.  This causes the imposter
            // to dissolve instead of popping into view.
            alpha /= 3;
            dst[i*4+3] = (U8)alpha;
         }
         else
         {
            dst[i*4+0] = dst[i*4+1] = dst[i*4+2] = dst[i*4+3] = 0;
         }
      }

   PROFILE_END(); // TSShapeInstance_snapshot_sb_separate
  
   PROFILE_START(TSShapeInstance_snapshot_sb_filter);

      // We now run a special kernel filter over the image that
      // averages color into the transparent areas.  This should
      // in essence give us a border around the edges of the 
      // imposter silhouette which fixes the artifacts around the
      // alpha test billboards.
      U8* dst2 = (U8*)imposterOut->getBits(0);

      _colorAverageFilter( mDim, dst, dst2 );
      
      if ( 0 )
      {
         FileStream fs;
         if ( fs.open( "./imposterout.png", Torque::FS::File::Write ) )
            imposterOut->writeBitmap( "png", fs );

         fs.close();

         if ( fs.open( "./temp.png", Torque::FS::File::Write ) )
            bmp->writeBitmap( "png", fs );

         fs.close();
      }
   

   PROFILE_END(); // TSShapeInstance_snapshot_sb_filter

   delete bmp;
}