Shaders Easier Blur Shader

Tyg

Member
Most blur shaders use repeatedly copying the image and shifting it which is pretty demanding and inefficient
Gamemaker has some functions that make it super easy

create a shader

in your objects draw event

sha = Blur;
gpu_set_tex_mip_enable(mip_on); // turn mipmapping on
gpu_set_tex_filter(tf_anisotropic); // anisotropic so its not chunky
shader_set(sha);
shader_set_uniform_f(shader_get_uniform(sha,"iTime"), current_time/1000); // Only needed if you want to do things like pulse the blur
shader_set_uniform_f(shader_get_uniform(sha,"iBlur"), 6); // can be a variable or even put in the shader instead of a uniform
draw_self();
shader_reset();
gpu_set_tex_mip_enable(mip_off); // turn off mipmapping

the shader:

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float iBlur; // can be a var instead of a uniform
uniform float iTime; // not required

void main()
{
// float ti = fract(iTime)*10.; // not required but can be used for changeing blur or use sin() function for pulsating
gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord, iBlur ); // all you need to do is have the 3rd paramater bias (iBlur) which works now that we have mippmapping on can also iBlur*ti or just ti for 3rd parameter
}

blur values should be between 0.0 and 9.0

You could also use this to make LOD functions within the shader :)
 

rytan451

Member
For convenience:

GML:
sha = Blur;
gpu_set_tex_mip_enable(mip_on); // turn mipmapping on
gpu_set_tex_filter(tf_anisotropic); // anisotropic so its not chunky
shader_set(sha);
shader_set_uniform_f(shader_get_uniform(sha,"iTime"), current_time/1000); // Only needed if you want to do things like pulse the blur
shader_set_uniform_f(shader_get_uniform(sha,"iBlur"), 6); // can be a variable or even put in the shader instead of a uniform
draw_self();
shader_reset();
gpu_set_tex_mip_enable(mip_off); // turn off mipmapping
C:
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float iBlur; // can be a var instead of a uniform
uniform float iTime; // not required

void main()
{
    // float ti = fract(iTime)*10.; // not required but can be used for changeing blur or use sin() function for pulsating
    gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord, iBlur ); // all you need to do is have the 3rd paramater bias (iBlur) which works now that we have mippmapping on can also iBlur*ti or just ti for 3rd parameter
}
What you're actually doing is using a mipmapped version of the image. This means you're getting the GPU to scale down the image, then scale it up again. This approximates a blur, but it can actually move objects on screen. Furthermore, this actually is less efficient, as it scales down and scales up the entire loaded texture page, instead of just sampling from the application surface multiple times. Not only is it being scaled down, it's being scaled down to many smaller images (if your texture page is 2048x2048, it will scale the texture down to create 11 new textures). For this reason, I do not think that this is more efficient than simply sampling from a texture multiple times before applying a gaussian blur.
 

Tyg

Member
What it is actually doing is taking the sprite texture and applying a filter
It takes the sprites texture once, and goes through the gpus filter thats it, the iblur and itime are optional, iBlur could be a hard coded number like 6 and not even use a uniform
It takes the sprite texture and applies a filter, its built in to the GPU, so im not sure where your getting your information
I think your implying CPU operations would be more efficient than the GPUs built in, well your entitled to your opinion
But thats not the case, I put this here because most people don't know about the 3rd pamameter and how to use it
Because Gamemaker does not use the texture2DLod in the fragment shader and this is what it was intended for

in your objects draw event

gpu_set_tex_mip_enable(mip_on); // turn mipmapping on
gpu_set_tex_filter(tf_anisotropic); // anisotropic so its not chunky
draw_self();
shader_reset();
gpu_set_tex_mip_enable(mip_off); // turn off mipmapping

the shader:

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord, 6. );
}

This is all you really need, and yes it can be used on a sprite, surface, layer or even room
 
Last edited:
Top