GameMaker:Studio Shader カラー調整

 shader   greyscale   GLSL_ES 

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

グレースケールの派生。グレースケールに色をオーバーレイしたような効果を出せる。本来の色〜グレースケール〜単色化と幅広く表現可能。

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

    1. Create
    2. Draw
    3. DrawGUI

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

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

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

キーボードの Q と W と E と R キーで値を上に変更可能。

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

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

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

シェーダー名:SH_AjustColor

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.0);
    v_vColour   = in_Colour;
    v_vTexcoord = in_TextureCoord;
}

Fragment Shader

varying vec2 v_vTexcoord;
varying vec4 v_vColour;

uniform float colourR;
uniform float colourG;
uniform float colourB;
uniform float colourA;

void main()
{
    vec4 col      = texture2D( gm_BaseTexture, v_vTexcoord );
    gl_FragColor  = v_vColour * vec4(col.r+colourR,col.r+colourG,col.r+colourB, col.a-colourA);
}

gl_FragColor は、あえて vec4 の要素に col.r を三連続で指定してある。

vec4(col.r+colourR,col.r+colourG,col.r+colourB, col.a-colourA);

この部分については

vec4(col.r+colourR,col.g+colourG,col.b+colourB, col.a-colourA);

上記でも良いが描画結果は異なる。

ユーザ定義関数 Init_Shader_AjustColor

///Init_AjustColor();
    if (!shader_is_compiled(SH_AjustColor)) {
       show_message("Your hardware doesn't support shader - SH_greyscale");
    }
    else{
       uni_colourR = shader_get_uniform(SH_AjustColor,"colourR");
       var_colourR = 0;
       uni_colourG = shader_get_uniform(SH_AjustColor,"colourG");
       var_colourG = 0;
       uni_colourB = shader_get_uniform(SH_AjustColor,"colourB");
       var_colourB = 0;
       uni_colourA = shader_get_uniform(SH_AjustColor,"colourA");
       var_colourA = 0;
    };

ユーザ定義関数 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_Keys

///Debug_Keys();
var w,z;
w = var_colourA;
z = 0.01;
if keyboard_check(ord('Q')) and w<1 var_colourA += z;
if keyboard_check(ord('A')) and w>0 var_colourA -= z;

var a;
a = var_colourR;
if keyboard_check(ord('W')) and a<1 var_colourR += z;
if keyboard_check(ord('S')) and a>0 var_colourR -= z;

var b;
b = var_colourG;
if keyboard_check(ord('E')) and b<1 var_colourG += z;
if keyboard_check(ord('D')) and b>0 var_colourG -= z;

var c;
c = var_colourB;
if keyboard_check(ord('R')) and c<1 var_colourB += z;
if keyboard_check(ord('F')) and c>0 var_colourB -= z;

ユーザ定義関数 DrawGUIEv_AjustColor

///DrawGUIEv_AjustColor();
shader_set(SH_AjustColor);
shader_set_uniform_f(uni_colourR, var_colourR);
shader_set_uniform_f(uni_colourG, var_colourG);
shader_set_uniform_f(uni_colourB, var_colourB);
shader_set_uniform_f(uni_colourA, var_colourA);
draw_surface_ext(application_surface, 0,0, 1,1, 0, -1,1);
shader_reset();

実際のイベント処理

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

Create Event

///Init
draw_set_font(font0);

Init_Shader_AjustColor();

Draw Event

DrawEv_SetSprites();

Draw GUI Event

///Draw gui

Debug_Keys();
DrawGUIEv_AjustColor();

var a,b,c;
a = room_height-250;
b = (room_width>>1);


draw_set_colour(c_teal);
draw_text(100, a,"Shader :: Colour Ajust(push keys Q|W|E|R and A|S|D|F)");

draw_set_colour(c_black);
draw_text(100,600,"var_colourA = " + string(var_colourA));

draw_set_colour(c_red);
draw_text(100,640,"var_colourR = " + string(var_colourR));

draw_set_colour(c_green);
draw_text(100,680,"var_colourG = " + string(var_colourG));

draw_set_colour(c_blue);
draw_text(100,720,"var_colourB = " + string(var_colourB));

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

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

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




次へ

前へ