GameMaker:Studio Shader グレースケール 改

 shader   greyscale   GLSL_ES 

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

画像のグレースケール化効果、別バージョン。

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

上記シェーダとの違いについて、

別バージョンは最初からグレースケール化される値を取り、引数の変化でグレースケールからブラックアウトもしくはホワイトアウトするトランジション的視覚効果がある。上記URLのグレースケールは本来の色から引数の変化によって徐々にグレースケール化される視覚効果がある。

どちらのサンプルも DrawGUI で描画する application_surface のサイズを縮小して表示しているが、別バージョンの方は縦横比率を維持したまま縮小する指定を Vertex Shader の

ul_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.6);

から「1.6」としている。

vec4(in_Position, 1.0) の場合は等倍だが、GM:S/GMLの側で draw_surface_ext を使っても application_surface のスケールの変更はできる。シェーダの側で縮小するか、GM:S 側で縮小を指示するかの違い。


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

    1. Create
    2. Draw
    3. DrawGUI

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

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

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

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

Simple Shader Samples

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

値は 0 〜 1 までの範囲( FadeA ) と 0 〜 3 までの範囲( FadeB ) で制限。要 WebGL、Google Chrome/FireFox 等で動作を確認。

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

シェーダー名:SH_greyscale_B

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_vTexcoord;
varying vec4 v_vColour;

void main()
{
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.6);
    
    v_vColour   = in_Colour;
    v_vTexcoord = in_TextureCoord;
}

Fragment Shader

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float fadeA;
uniform float fadeB;

void main()
{
    vec4 col      = texture2D( gm_BaseTexture, v_vTexcoord );
    //float average = min(1.0, ((col.r+col.g+col.b)/3.0) );
    float average = min(fadeA, ((col.r+col.g+col.b)/fadeB) );
    gl_FragColor  = v_vColour * vec4(average,average,average, col.a);
}

ユーザ定義関数 Init_GreyscaleShaderB

///Init_GreyscaleShaderB();
    if (!shader_is_compiled(SH_greyscale_B)) {
       show_message("Your hardware doesn't support shader - SH_greyscale");
    }
    else{
       uni_greyscale_fadeA = shader_get_uniform(SH_greyscale_B,"fadeA");
       var_greyscale_fadeA = 1.0;
       uni_greyscale_fadeB = shader_get_uniform(SH_greyscale_B,"fadeB");
       var_greyscale_fadeB = 3;
    };

ユーザ定義関数 DrawEv_SetSprites

///DrawEv_SetSprites();
var a = sprite_get_height(banners);
    for (var i=0;i<3;i++){
        draw_sprite(banners,i,-100,a*i);
    };

ユーザ定義関数 Debug_ShowStatusB

///Debug_ShowStatusB();
var w,z;
z = 0.01;
w = var_greyscale_fadeA;
if keyboard_check(ord('Q')) and w<1 var_greyscale_fadeA += z;
if keyboard_check(ord('A')) and w>0 var_greyscale_fadeA -= z;
var u,v;
u = 0.1;
v = var_greyscale_fadeB;
if keyboard_check(ord('W')) and v<3 var_greyscale_fadeB += u;
if keyboard_check(ord('S')) and v>0 var_greyscale_fadeB -= u;

var c,d,e;
c = c_red;
d = display_get_gui_width()>>1;
e = display_get_gui_height();
draw_line_colour(d,0,d,e,c,c);

var a,b
a = sprite_get_height(banners);
b = ((a<<1) + a);
draw_circle_colour(d,b,40,c,c,0);

ユーザ定義関数 DrawGUIEv_GreyscaleB

///DrawGUIEv_GreyscaleB(width_scale);
var a = argument0;
shader_set(SH_greyscale_B);
shader_set_uniform_f(uni_greyscale_fadeA, var_greyscale_fadeA);
shader_set_uniform_f(uni_greyscale_fadeB, var_greyscale_fadeB);
draw_surface_ext(application_surface, 0,0, a,1, 0, -1,1);
shader_reset();

実際のイベント処理

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

Create Event

///Init
Init_GreyscaleShaderB();

draw_set_font(font0);
/* Variables For Debug */
Debug_Scale = 1;

Draw Event

DrawEv_SetSprites();

Draw GUI Event

///Draw gui

Debug_ShowStatusB();

DrawGUIEv_GreyscaleB(Debug_Scale);

var a,b,c,d;
a = room_height-100;
b = (room_width>>1);
c = var_greyscale_fadeA;
d = var_greyscale_fadeB;

draw_set_colour(c_white);
draw_text(100,  a-300,"Greyscale_Another_Version");

draw_set_colour(c_red);
draw_text(b+100,a-100,"fadeA between 0 ~ 1");
draw_text(b+100,a- 50,"fadeB between 0 ~ 3");

draw_set_colour(c_black);
draw_text(100,  a,    "Q|W = up value");
draw_text(100,  a+40, "A|S = down value");
draw_text(b+100,a,    "var_greyscale_fadeA = "+string(c));
draw_text(b+100,a+40, "var_greyscale_fadeB = "+string(d));

application_surface を対象としてシェーダでエフェクトをかけます。今回はサイズ変更処理を Vertex シェーダ側で指定してあります。

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

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




次へ

前へ