GameMaker:Studio Shader UVを利用した描画位置変更

 shader   uv   GLSL_ES 

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

対象( ここでは application_surface ) の描画位置を uv 値を使って変更するシェーダ。キー操作で画面を動かせます。応用すれば画面をシェイクしたり画面遷移 ( トランジション ) にも利用可能。

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

    1. Create
    2. Draw
    3. DrawGUI

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

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

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

キーボードの W と A と S と D キーで値を変更可能。

値は -1 〜 1 までの範囲で制限。要 WebGL、Google Chrome/FireFox 等で動作を確認。

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

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);
    v_texcoord = in_TextureCoord;
}

Fragment Shader

varying vec2 v_texcoord;

uniform float pixel_x;
uniform float pixel_y;

void main()
{ 
    vec2 uv      = vec2(v_texcoord.x-pixel_x, v_texcoord.y-pixel_y);
    gl_FragColor = texture2D( gm_BaseTexture, uv );
}

ユーザ定義関数 Init_Shader_uvmove

///Init_Shader_uvmove();

    if (!shader_is_compiled(SH_uvmove)) {
        show_message("Your hardware doesn't support shader - SH_uvmove");
    }
    else{
        uni_pixel_x = shader_get_uniform(SH_uvmove,"pixel_x");
        var_pixel_x = 0.0;
        uni_pixel_y = shader_get_uniform(SH_uvmove,"pixel_y");
        var_pixel_y = 0.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_Keys

///Debug_keys();
var u,v,w,z;
u = 1;
v = var_pixel_x;
w = var_pixel_y;
z = 0.01;
if keyboard_check(ord('W')) and w>-u var_pixel_y -= z;
if keyboard_check(ord('A')) and v>-u var_pixel_x -= z;
if keyboard_check(ord('S')) and w< u var_pixel_y += z;
if keyboard_check(ord('D')) and v< u var_pixel_x += z;

var a,b,c,d,e,f;
a  = 0;
b  = 40;
c  = "push keys >>> W | A | S | D";
d  = "var_pixel_x = "+string(var_pixel_x);
e  = "var_pixel_y = "+string(var_pixel_y);
f  = 600;

draw_set_colour(c_red);
draw_text(a,0,"Real FPS: "+string(fps_real));
draw_set_colour(c_white);
draw_text(a,b,c);
draw_text(a+f,0,d);
draw_text(a+f,b,e);

ユーザ定義関数 DrawGUIEv_uvmove

///DrawGUIEv_uvmove();

shader_set(SH_uvmove);
shader_set_uniform_f(uni_pixel_x, var_pixel_x);
shader_set_uniform_f(uni_pixel_y, var_pixel_y);
draw_surface_ext(application_surface, 0,0, 1,1, 0, -1,1); 
shader_reset();

実際のイベント処理

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

Create Event

draw_set_font(font0);

Init_Shader_uvmove();

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

Draw Event

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

Draw GUI Event

DrawGUIEv_uvmove();

Debug_keys();

DrawEv_WalkingRobo();//for GUI

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

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

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




次へ

前へ