GameMaker:Studio Shader Transition(円)改善版

 shader   transition   GLSL_ES 

配布されていたシェーダサンプルを独自に作り直したもの。

円を描くロジックを見直し、フラグメントでは組み込み関数の distance を使って簡潔に記述。オリジナルの方法だと円にジャギー( 階段状のギザギザ ) が発生するため、これを軽減するためのアンチエイリアス的処理追加。

左:滑らかなカーブ、右:ジャギーが見える

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

    1. Create
    2. Draw
    3. DrawGUI

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

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

参考動作:http://prester.org/html5/13_shader_circle_transition_Rev2/

参考 :Shader_transition_circle

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

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

シェーダー名:SH_transition_circle_Rev2

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;// x,y is a screen space coordinate.
    v_vColour   = in_Colour;
    v_vTexcoord = in_TextureCoord;
}

Fragment Shader

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

uniform vec3 v_MaskParams;// x,y=position, z=radius, 
const float offset = 1.0;//強いアンチエイリアスをかける場合は 2.0 以上にする

void main()
{
    float dist  = distance(v_vPosition.xy , v_MaskParams.xy);
        if ( dist > v_MaskParams.z ){
           float opt = dist - v_MaskParams.z;
                if (opt < offset ){
                    //opt          = v_vColour.a - (opt / offset);//強いアンチエイリアス == Offset値を2.0以上にする
                    opt          = v_vColour.a - opt;//通常はこれで十分綺麗な円に見える
                    gl_FragColor = vec4(v_vColour.rgb, opt) * texture2D( gm_BaseTexture, v_vTexcoord );
                }
                else{
                    discard;// throw pixel away if it's out of range
                }
        }
        else{
            gl_FragColor = v_vColour * texture2D( gm_BaseTexture, v_vTexcoord );
        }
}

ユーザ定義関数 Init_Shader_transition_circle

///Init_Shader_transition_circle();

    if (!shader_is_compiled(SH_transition_circle_Rev2)) {
        show_message("Your hardware doesn't support shader - SH_transition_circle_Rev2");
    }
    else{
        v_mask = shader_get_uniform(SH_transition_circle_Rev2, "v_MaskParams");
        Length = 0.0;
        Time   = 2.0;
    };

ユーザ定義関数 DrawEv_transition_circle

///DrawEv_transition_circle();
draw_self();

var a,b,c,d,e;
a = Length;// Circle
b = mouse_x;//Screen Center position X
c = mouse_y;//Screen Center position Y
d = room_width;
e = room_height;

shader_set(SH_transition_circle_Rev2);
shader_set_uniform_f(v_mask, b, c, a);
draw_background_stretched(background0, 0, 0, d, e);
draw_set_colour(c_red);
draw_text(40,140,"Hello Hello Hello World!");
shader_reset();

    if ( a < 0 or a > d ) Time *= -1;

Length += Time;

ユーザ定義関数 DrawGUI_Show_Status

///DrawGUI_Show_Status();
draw_set_colour(c_green);
draw_text(10,10,"Shader SH_transition_circle_Rev2");

draw_set_colour(c_blue);
draw_text(10,room_width-100,"length =  "+string_format(Length,1,5));

実際のイベント処理

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

Create Event

draw_set_font(font0);

Init_Shader_transition_circle_Rev2();

Draw Event

DrawEv_transition_circle();

Draw GUI Event

DrawGUI_Show_Status();

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

ユーザ定義関数である DrawEv_transition_circle(); でシェーダ処理を行っている。




次へ

前へ