How to implement Bloom post effect in Flash
First of all, I really want to convey a huge hello to the wonderful actor and the walking post-effect all rolled into one: Orlando Bloom. As long as Google exists, you won’t be forgotten.
First of all, it is worthwhile to understand that the calculation of these post-effects cannot be performed on the video card. This is due to one wonderful limitation, for which we love the GPU - at the same time, the color of several pixels is calculated. Because of this, you will not be able to accurately know the color of the "neighboring" pixel, so necessary when implementing these effects. Therefore, we will calculate the final picture on the CPU.Post-effects can significantly smooth out irregularities and ugly edges of three-dimensional graphics, and significantly improves the picture. The speed of the post-effect is entirely dependent on the size of the view, respectively, the largest performance drop will be observed with a full-screen picture. Also, I want to mention that these effects do not apply to any particular engine and can be performed on any image from which BitmapData can be removed. This article will discuss the application of blur to a picture obtained with the alternativa3d engine. Who is still reading - I invite you to habrakat.
First of all, we need to ask the video card to return the rendered image to us in a form convenient for us. To do this, you must call the Context3D.drawToBitmapData () method. With an argument, this method accepts an object of type BitmapData, updated with every call to the present () method of the same context. If you use the alternativa3d engine, you just need to set the renderToBitmap property of the View instance to true. Then the rendered bitmapData can be obtained from the canvas property of the same instance.
It is generally accepted to use the following image blur algorithm:
With items 2 and 3, the built-in flash filter called BlurFilter does a great job. 1 and 4 are provided by applying the matrix of affine transformations when calling the draw method of the bitmapData instance. Well, the fifth point is easy to implement by setting the constructor parameters of the ColorTransform instance. All that remains is to show the picture on the screen, which the copy of the Alternative library added to the [child] Stage can cope without assistance: Image without post-processing and with it:

At the development stage, it can be very convenient to put the parameters _scaling, _power, _alpha and _quality into the static property of an arbitrary class in order to change their runtime and adjust the picture until the desired balance between beauty and performance is reached. Or let you change them directly to the user through the graphics settings menu.
Coming soon: HDR effect - brightening the picture and how to feel the buffer.
Part one. Bluer
Important limitation
Preparing a picture
First of all, we need to ask the video card to return the rendered image to us in a form convenient for us. To do this, you must call the Context3D.drawToBitmapData () method. With an argument, this method accepts an object of type BitmapData, updated with every call to the present () method of the same context. If you use the alternativa3d engine, you just need to set the renderToBitmap property of the View instance to true. Then the rendered bitmapData can be obtained from the canvas property of the same instance.
private function itsRenderTime(e:Event):void { //No, dad, no!
camera.view.renderToBitmap = true;
camera.render(stage3d);
realisePostEffect(camera.view.canvas);
}
Blur itself
It is generally accepted to use the following image blur algorithm:
- First, we reduce the image received from the renderer to reduce the load on the processor - it will have to perform the same rather difficult operation on each pixel.
- The next action we need to find out the average color of each of the neighboring current pixel and mix it with the color of the current in equal shares. If “enhanced” blurring is used, the colors of the neighbors of the neighbors are recognized; the influence of the color of such pixels is inversely proportional to the distance (perhaps even its square, did not go into details) to them from the current one.
- Step 2 can be repeated several times to enhance the quality of the blur. Theoretically, it can be performed an arbitrary number of times, however, experimentally, the best quality / performance ratio was established when performing the second paragraph three times. Smart articles say that in this way the closest approach to Gaussian blur is achieved, but you will not see the details in this article, so just take a word.
- The resulting blurry image is again stretched to the rendered size to fit.
- Blurred and rendered images are mixed with [semi] opacity blurred.
With items 2 and 3, the built-in flash filter called BlurFilter does a great job. 1 and 4 are provided by applying the matrix of affine transformations when calling the draw method of the bitmapData instance. Well, the fifth point is easy to implement by setting the constructor parameters of the ColorTransform instance. All that remains is to show the picture on the screen, which the copy of the Alternative library added to the [child] Stage can cope without assistance: Image without post-processing and with it:
private function realisePostEffect(canvas:BitmapData):void {
var _scaling:int = 4 //Уменьшаем нагрузку на процессор в 16 (4*4) раз.
var _power:int = 4 //Просим фильтр учитывать цвет соседей вплоть до четвёртого порядка
var _alpha:Number = .5 //Размытая и отрендеренная картинки будут смешиваться в равных долях
var _quality:int = 3 //Размытие каждого пиксела будет произведено трижды, во имя богини красоты текущей религии разработчика
var _cT:ColorTransform = new ColorTransform(1, 1, 1, _alpha);
var _bloomData:BitmapData = new BitmapData(canvas.width / _scaling, canvas.height / _scaling, true, 0);
var matrix:Matrix = new Matrix();
matrix.scale(1 / _scaling, 1 / _scaling);
_bloomData.draw(canvas, matrix, _cT);
_bloomData.applyFilter(_bloomData, _bloomData.rect, new Point(), new BlurFilter(_power, _power, _quality));
matrix.invert();
canvas.draw(_bloomData, matrix);
}

At the development stage, it can be very convenient to put the parameters _scaling, _power, _alpha and _quality into the static property of an arbitrary class in order to change their runtime and adjust the picture until the desired balance between beauty and performance is reached. Or let you change them directly to the user through the graphics settings menu.
Coming soon: HDR effect - brightening the picture and how to feel the buffer.