ワイプ(Wipe vertical)/下から上

 effect   wipe   discard   gl_FragCoord 

シンプルなワイプ、下から上にスプライトが消えていくエフェクトとして作成

オブジェクトを破壊する際にオブジェクトの外観として利用されているスプライトの描画で「オブジェクトの破壊」を表現したくて作られたシェーダ。

とてもシンプルなので簡単にゲームへ組み込めます。

オブジェクトをタッチするとワイプして消えるサンプル

イベントを一つのオブジェクトへまとめ、

上記四つのイベントへ収まるように作った。無駄な変数定義を排除、コードの使い回し簡単。

オブジェクトをマウスクリック/タッチすると時間差でオブジェクトが破壊されます。

破壊の表現としてシェーダによるワイプが実行されます。

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

HTML5( WebGL ) と Windows PC で微妙に描画結果が異なる場合があります。

シェーダー名:SH_Char_WipeVertical

参考動作:ワイプ(下から上)

OpenGL-ES_50px_May16 WebGL_50px_June16

Vertex Shader

 
//
// Character wipe (Vertical) : vertex shader
//
attribute vec3 in_Position;                  // (x,y,z)
attribute vec4 in_Colour;                    // (r,g,b,a)
attribute vec2 in_TextureCoord;              // (u,v)

varying vec2 v_vPosition;
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);
    v_vPosition = in_Position.xy;
    v_vTexcoord = in_TextureCoord;
    v_vColour   = in_Colour;
}
 
FragCoord について

GM:S の仕様として、GLSL ES 2.0 の全ビルトインをサポートしていません。gl_FragCoord が GM:S から利用することは出来なかったため、varying を使って自力で Fragment へ値を渡しています。

このため

varying vec2 v_vPosition;

として void main() 内では

v_vPosition   = in_Position.xy;

フラグメントシェーダへ頂点データを渡す処理を自分で記述。

Fragment Shader

 
//
// Character wipe (Vertical) : fragment shader
//
varying vec2 v_vPosition;
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float v_Mask;

void main()
{
    if ( v_vPosition.y >= v_Mask )
    {
        discard;// throw pixel away if it's out of range
    }
    else
    {
        gl_FragColor = v_vColour * texture2D(gm_BaseTexture, v_vTexcoord);
    }
}
 

フラグメントもほぼ PassThrough Shader と変わらず。異なる点はシェーダ内で「描画する部分」と「描画しない部分」を分割している点。

「指定した Y 位置より下は描画しない」という条件が

if ( v_vPosition.y >= v_Mask )

の部分で、本来ここは GLSL ES の組み込みである gl_FragCoord からピクセル座標を取得したかった。

しかし GMS がこのビルトインをサポートしていないためこの部分はあえて名前を変えて vec2 v_vPosition として手動で varying している。本来の gl_FragCoord は vec4 型のデータなので要注意。

v_vPosition.yはループ処理中のフラグメントシェーダ内におけるピクセルの Y 座標。

イベント処理

シェーダと1つのオブジェクトに4つのイベントを使って簡潔に。

Create Event

var a,b;
a = SH_Char_WipeVertical;

if !shader_is_compiled(a) 
{
    b = "ur hardware ain't support shader - SH_Char_WipeVertical";
    show_message(b);
}
else
{
    b        = "v_Mask";
    U_mask   = shader_get_uniform(a, b);
    MaskHigh = (y + sprite_get_height(sprite0));// Sprite Origin X,Y = (0,0)
    MaskWipe = 10.0;// const
};

Alarm 0

///Destroy
instance_destroy(id);

Step

///STEP
var a,b;
a = mouse_x;
b = mouse_y;

if mouse_check_button_pressed(mb_left)
{
    with(collision_point(a,b,penta,false,false))
    {
        alarm_set(0,room_speed);
    };

};

Draw

///Draw

/*  Shader Draw  */
if (alarm[0])
{
    shader_set(SH_Char_WipeVertical);
    shader_set_uniform_f(U_mask , MaskHigh);
    draw_self();
    shader_reset();
    
    
    /*  finalize  */
    if (MaskWipe > 0)
    {
        MaskHigh -= MaskWipe;
        if (MaskHigh < 0)
        {
            MaskWipe = 0;
            MaskHigh = y;
        };// IF.EnD.0
    };// IF.EnD.1
}
else draw_self();




前へ