kawase blur is an efficient way to fake approximate a gaussian blur by sneakin' a grip of texture samples over hardware texture filtering (gpu tex filter in gml). in gamemaker terms this means its a very fast blur that gives results that are close enough to a real gaussian filter that anyone who notices that its not gaussian probably has robotoeyes or is a top notch jraphics programmer. its a very fast, bandwidth efficient filter for when you want to do a bloom or a depth of field or hide your face during a crime and cannot afford a full blown blur.
originally the method was developed by masaki kawase and presented in a 2003 GDC talk, and the dual filtering method was introduced at siggraph 2015 by a homie named marius bjørge.
most blurring works the same way: the current pixel's color is based on the average value of the colors of its neighboring pixels. to average that color, we usually go "okay the pixel to the right is red and the pixel to the left is black, red + black is red because black is zero, divided by two because we sampled two pixels gives us a final result of half red. effectively meaning that the current pixel's color maths out like this: (1 + 0) / 2 = 0.5. that process of getting the average color is what blurs the image, and there are a few ways to choose the neighbors. you might choose them in a radial pattern, in a straight up box, or in a gaussian window. a lot of the time you will do this multiple times to make things extra fuzzy. each of these methods have their own pros and cons and costs.
so there is the kawase blur! its method of getting the average color begins by turning on hardware filtering, then for each pixel, the corners of four neighboring pixels are sampled. since the sample is taken in the corner, and hardware filtering is enabled, this is the same as sampling four pixels in one spot. by using this trick, the blur is made by turning the color of the current pixel into the average color of its sixteen neighbors. by doing this across multiple passes, which is called ping-ponging, you can spread the blur out to make it nice and blurry without artifacts. i made this gif to illustrate how it works:
it begins with a single pixel in a grid of pixels. the red square is our current pixel, and the eggshell squares are all the other pixels. in the first pass, the color at each blue dot is sampled, and since it is in the corner of each neighbor then the color of the red pixel becomes the average color of every pixel within the yellow area. then we move to the second pass, which samples four groups of pixels a little further out. so now the color of our red pixel is the average color of everything in yellow. on a third pass we move our samples further out again, adding even more colors to our red pixel. each pass adds its average colors to the current pixel.
the regular kawase blur is done as a classic ping pong: it applies the blur to each pass without altering the resolution of the samples. the dual filter is a little bit different in that it downsamples the resolution of the where the samples are made over each pass, and then does an equal number of passes where the samples are made on the already blurred stuff but at upscaled resolutions. this basically means that the dual filter breaks the picture down while blurring it, then puts it back together while making it bigger. this gives us results pretty results even cheaper than the single filter!
first you will want to put the yymps file in your game by downloading it from here and draggin' its ass over to your project. then its as simple as calling kawase_blur() and drawing the surface it returns.
example:
var blurry_picture = kawase_blur(application_surface, 2);
draw_surface(blurry_picture, 0, 0);| kawase_blur(source_surface, step_count, [sample_distance]) |
|---|
| this is the function that does the blurring! |
| source_surface: the surface you want to blur |
| step_count: the number of passes to make; the more the blurrier |
| sample_distance: optional argument to change the sample distance; by default its 0.5 which is nice |
there is a static function that will allow you to free the surfaces used with this blur if you need to. this function reuses surfaces, however, so you generally wont need to worry about it. if you do wanna do that tho you would call kawase_blur.clean_up()
go nuts just leave me out of it. you can use the gml and the shader code in any project you want, without attribution, but please try to link to kawase and bjørge.
