GameMaker:Studio Shader ガウスぼかし
配布されていたシェーダのサンプルを整理したもの
ガウスぼかし効果。
イベントを一つのオブジェクトへまとめるようにし、
- Create
- Draw
- DrawGUI
上記の三つのイベントへ収まるように作った。そして無駄な変数定義を全て排除。
なるべくユーザ定義関数化し、コードの使い回しが簡単。
参考動作:http://prester.org/html5/gms_shader_gaussian/
参考(YoYoGames MarketPlace):xygthop3’s Shader Resources
キーボードの Q と A キーで Blur_amount の値を変更可能。
値クランプ処理無し。要 WebGL、Google Chrome/FireFox 等で動作を確認。
このサンプルはオリジナル版に対して改変を加えて有ります。オリジナル版では Surface を二枚使って、その内一枚の Surface を Views とリンクさせて使っています。改変は主にこの部分で、改変したサンプルでは Surface は一枚のみを使用、あとは application_surface を用いています。具体的な処理は DrawGUIEv_gaussian を見てください。
オリジナル版の処理も DrawGUIEv_gaussian_for_Views というユーザ定義関数に収めて有ります。この関数を利用する場合は、初期化処理で省いてあるもう一枚の surface と views をリンクさせる処理、及び、room の設定から Views に関するオプションを有効にすること。
HTML5( WebGL ) と Windows PC で微妙に描画結果が異なる場合があります。特に引数値が 0 の場合の描画結果に注意。
値クランプ処理無し。要 WebGL、Google Chrome/FireFox 等で動作を確認。
このサンプルはオリジナル版に対して改変を加えて有ります。オリジナル版では Surface を二枚使って、その内一枚の Surface を Views とリンクさせて使っています。改変は主にこの部分で、改変したサンプルでは Surface は一枚のみを使用、あとは application_surface を用いています。具体的な処理は DrawGUIEv_gaussian を見てください。
オリジナル版の処理も DrawGUIEv_gaussian_for_Views というユーザ定義関数に収めて有ります。この関数を利用する場合は、初期化処理で省いてあるもう一枚の surface と views をリンクさせる処理、及び、room の設定から Views に関するオプションを有効にすること。
HTML5( WebGL ) と Windows PC で微妙に描画結果が異なる場合があります。特に引数値が 0 の場合の描画結果に注意。
今回はシェーダを二つ使います。
シェーダー名 1:SH_gaussian_vertical
シェーダー名 2:SH_gaussian_horizontal
SH_gaussian_vertical . Vertex Shader
attribute vec3 in_Position;
attribute vec2 in_TextureCoord;
varying vec2 v_texcoord;
void main()
{
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);
v_texcoord = in_TextureCoord;
}
SH_gaussian_vertical . Fragment Shader
varying vec2 v_texcoord;
uniform vec2 resolution;
uniform float blur_amount;
void main()
{
float blurSize = 1.0/resolution.y * blur_amount;
vec4 sum = vec4(0.0);
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y - 4.0*blurSize)) * 0.05;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y - 3.0*blurSize)) * 0.09;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y - 2.0*blurSize)) * 0.12;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y - blurSize)) * 0.15;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y)) * 0.16;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y + blurSize)) * 0.15;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y + 2.0*blurSize)) * 0.12;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y + 3.0*blurSize)) * 0.09;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y + 4.0*blurSize)) * 0.05;
gl_FragColor = sum;
}
SH_gaussian_horizontal . Vertex Shader
attribute vec3 in_Position;
attribute vec2 in_TextureCoord;
varying vec2 v_texcoord;
void main()
{
gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);
v_texcoord = in_TextureCoord;
}
SH_gaussian_horizontal . Fragment Shader
varying vec2 v_texcoord;
uniform vec2 resolution;
uniform float blur_amount;
void main()
{
float blurSize = 1.0/resolution.x * blur_amount;
vec4 sum = vec4(0.0);
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x - 4.0*blurSize, v_texcoord.y)) * 0.05;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x - 3.0*blurSize, v_texcoord.y)) * 0.09;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x - 2.0*blurSize, v_texcoord.y)) * 0.12;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x - blurSize, v_texcoord.y)) * 0.15;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x, v_texcoord.y)) * 0.16;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x + blurSize, v_texcoord.y)) * 0.15;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x + 2.0*blurSize, v_texcoord.y)) * 0.12;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x + 3.0*blurSize, v_texcoord.y)) * 0.09;
sum += texture2D(gm_BaseTexture, vec2(v_texcoord.x + 4.0*blurSize, v_texcoord.y)) * 0.05;
gl_FragColor = sum;
}
ユーザ定義関数 Init_Shader_gaussian
///Init_Shader_gaussian();
if (!shader_is_compiled(SH_gaussian_vertical) or !shader_is_compiled(SH_gaussian_horizontal)) {
show_message("Your hardware doesn't support shader - SH_gaussian_Vert or Hori");
}
else{
var a,b,c,d;
a = view_wview;
b = view_hview;
c = "resolution";
d = "blur_amount";
/* for Shaders */
uni_resolution_hoz = shader_get_uniform(SH_gaussian_horizontal, c);
uni_resolution_vert = shader_get_uniform(SH_gaussian_vertical, c);
var_resolution_x = a;
var_resolution_y = b;
uni_blur_amount_hoz = shader_get_uniform(SH_gaussian_vertical, d);
uni_blur_amount_vert = shader_get_uniform(SH_gaussian_horizontal, d);
var_blur_amount = 1.0;
/* for Surfaces */
final_surface = surface_create(a, b);
/*
surf = surface_create(a, b);// for Enable of Views
view_surface_id[0] = surf;
*/
/* for Debug */
shader_enabled = true;
};
ユーザ定義関数 DrawGUIEv_gaussian
///DrawGUIEv_gaussian();
if shader_enabled {
//Do horizontal blur first
if surface_exists(final_surface){
surface_set_target(final_surface);
shader_set(SH_gaussian_horizontal);
shader_set_uniform_f(uni_resolution_hoz, var_resolution_x, var_resolution_y);
shader_set_uniform_f(uni_blur_amount_hoz, var_blur_amount);
draw_surface(application_surface, 0, 0);
shader_reset();
surface_reset_target();
//Do vertical blur last
shader_set(SH_gaussian_vertical);
shader_set_uniform_f(uni_resolution_vert, var_resolution_x, var_resolution_y);
shader_set_uniform_f(uni_blur_amount_vert, var_blur_amount);
draw_surface(final_surface, 0, 0);
shader_reset();
}
else{
final_surface = surface_create(view_wview, view_hview);
};
};
ユーザ定義関数 DrawGUIEv_gaussian_for_Views
///DrawGUIEv_gaussian_for_Views();
/*
This function must be set Enable of views.
plz check > room settings
> views tab
>> turn ON both checkboxs "Enable the use of Views" & "Visible when room starts"
if shader_enabled {
//Do horizontal blur first
surface_set_target(final_surface);
shader_set(SH_gaussian_horizontal);
shader_set_uniform_f(uni_resolution_hoz, var_resolution_x, var_resolution_y);
shader_set_uniform_f(uni_blur_amount_hoz, var_blur_amount);
draw_surface(surf, 0, 0);
shader_reset();
surface_reset_target();
//Do vertical blur last
shader_set(SH_gaussian_vertical);
shader_set_uniform_f(uni_resolution_vert, var_resolution_x, var_resolution_y);
shader_set_uniform_f(uni_blur_amount_vert, var_blur_amount);
draw_surface(final_surface, 0, 0);
shader_reset();
};
*/
この関数は未使用です。オリジナル版の処理と同じものなので、もしも利用する場合には Rooms の設定から views 関連のオプションを有効化してください。
ユーザ定義関数 Debug_Keys
///Debug_Keys();
if keyboard_check(ord('Q')) var_blur_amount += 0.01;
if keyboard_check(ord('A')) var_blur_amount -= 0.01;
if keyboard_check_pressed(vk_space) shader_enabled = !shader_enabled;
draw_text(10, 0, "Real FPS: "+string(fps_real));
draw_text(10, 40,"Blur amount(Q & A to adjust): "+string(var_blur_amount));
draw_text(10, room_height-90,"Spacebar to toggle shader");
実際のイベント処理
シェーダと4つのユーザ定義関数を使って簡潔なイベントを作成。
Create Event
draw_set_font(font0);
draw_set_color(c_white);
Init_Shader_gaussian();
Draw Event
draw_background_stretched(background0, 0, 0, room_width, room_height);
draw_self();
Draw GUI Event
DrawGUIEv_gaussian();
Debug_Keys();
application_surface を対象としてシェーダでエフェクトをかけます。( オリジナル版では Views と Surface をリンクさせて描画に利用します )
Draw イベントで描画した画面を DrawGUI へ描画するという手順。シェーダで application_surface 全体を対象にする場合は DrawGUI のタイミングで描画するのが無難。
ユーザ定義関数である DrawGUIEv_gaussian でシェーダ処理を行っている。今回のサンプルはオリジナル版と同じく、gaussian_vertical と gaussian_horizontal という二つのシェーダを使って最終出力結果を得ています。
次へ
前へ