GameMaker:Studio Shader モザイク/通常版

 shader   mosaic   GLSL_ES 

配布されていたシェーダのサンプルを整理したもの。

( 参考:Demosタブ → YoYo Demos → Advanced → Simple_Shader_Examples )

Simple Shader Samples

画像にモザイク処理をかける効果。計算コストが低い通常版モザイク。計算コストの高い方法を採用した高品質版モザイクもある。

関連:http://prester.org/static/obake/post/shader_mosaic_HQ/

イベントを一つのオブジェクトへまとめるようにし、

    1. Create
    2. Draw
    3. DrawGUI

上記の三つのイベントへ収まるように作った。そして無駄な変数定義を全て排除。

なるべくユーザ定義関数化し、コードの使い回しが簡単。

参考動作:http://prester.org/html5/gms_shader_mosaic/

キーボードの Q と A キーで値を変更可能。値は 500 〜 -500 までの範囲で制限。

要 WebGL、Google Chrome/FireFox 等で動作を確認。

HTML5( WebGL ) と Windows PC で微妙に描画結果が異なる場合があります。特に引数値が 0 の場合の描画結果に注意。
シェーダー名:SH_mosaic

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;
}

Fragment Shader

varying vec2 v_texcoord;

uniform vec2 resolution;
uniform float pixel_amount;

void main()
{ 
    vec2 res     = vec2(1.0, resolution.x/resolution.y);
    vec2 size    = vec2(res.x/pixel_amount, res.y/pixel_amount);
    vec2 uv      = v_texcoord - mod(v_texcoord,size);
    gl_FragColor = texture2D( gm_BaseTexture, uv );
}

特定のピクセルに対して色を求める方法なので計算コストは低い。その代わり品質も低いため、描画結果にムラを生じる場合がある。

ユーザ定義関数 Init_Shader_Mosaic

///Init_Shader_Mosaic();

    if (!shader_is_compiled(SH_mosaic)) {
        show_message("Your hardware doesn't support shader - SH_mosaic");
    }
    else{
        uni_resolution   = shader_get_uniform(SH_mosaic,"resolution");
        var_resolution_x = display_get_gui_width()//view_wview;
        var_resolution_y = display_get_gui_height()//view_hview;
        
        uni_pixel_amount = shader_get_uniform(SH_mosaic,"pixel_amount");
        var_pixel_amount = 50.0;
    };

ユーザ定義関数 DrawEv_WalkingRobo

///DrawEv_WalkingRobo();
var a,b,c,d;
a = sprite_get_number(rb);
b = Robot_ImageIndex;
b++;
   if (b > a) b = 0;
Robot_ImageIndex = b;
c = room_width>>1;
d = room_height>>1;
draw_sprite(rb,b,c,d);

ユーザ定義関数 Debug_ShowStatus

///Debug_ShowStatus();
var w,z;
z = 5;
w = var_pixel_amount;
if keyboard_check(ord('Q')) and w< 500 var_pixel_amount += z;
if keyboard_check(ord('A')) and w>-500 var_pixel_amount -= z;

var a,b,c;
a  = 0;
b  = 40;
c  = "Pixel amount (Q & A to adjust): ";
c += string(var_pixel_amount);

draw_text(a,0,"Real FPS: "+string(fps_real));
draw_text(a,b,c);

ユーザ定義関数 DrawGUIEv_Mosaic

///DrawGUIEv_mosaic();

shader_set(SH_mosaic);
shader_set_uniform_f(uni_resolution, var_resolution_x, var_resolution_y);
shader_set_uniform_f(uni_pixel_amount, var_pixel_amount);
draw_surface_ext(application_surface, 0,0, 1,1, 0, -1,1); 
shader_reset();

実際のイベント処理

シェーダと4つのユーザ定義関数を使って簡潔なイベントを作成。

Create Event

draw_set_font(font0);
draw_set_colour(c_white);

Init_Shader_Mosaic();

/* Instance Variable for draw_sprite */
Robot_ImageIndex = 0;

Draw Event

draw_self();
DrawEv_WalkingRobo();//draw with application surface

Draw GUI Event

DrawGUIEv_Mosaic();

Debug_ShowStatus();

DrawEv_WalkingRobo();//for GUI

application_surface を対象としてシェーダでエフェクトをかけます。

Draw イベントで描画した画面を DrawGUI へ描画するという手順。シェーダで application_surface 全体を対象にする場合は DrawGUI のタイミングで描画するのが無難。

ユーザ定義関数である DrawGUIEv_Mosaic でシェーダ処理を行っている。アクションの実行されるタイミングなどを色々変えて描画結果の違いを試すと良い。

ロボットのアニメーションはモザイク処理したものを Draw イベントで描画し、同じ物を DrawGUI でも描画することによってあえて二重化表示している。




次へ

前へ