グレースケール ( Greyscale Another ver)

 colour   greyscale   min   safari 

{{< twitter >}}

画像のグレースケール化、別バージョン。計算手法に単純平均法を用いた例。

前回はグレースケール化の適用率を値で調整したが、今回はグレースケール化した後に値の調整でホワイトアウトかブラックアウトかなど選択的に画面を変化させることができる。

グレースケール化するための計算も前回と異なり HDTV 係数は用いず、GLSL ES 組み込み関数からも内積( dot product ) や mix を使わず min で済ます。

計算コストは低い。

GameMaker:Studio Shader Greyscale Another Version Screenshot

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

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

    関連( prester.org ) Greyscale with fade

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

    YoYoGames Simple Shader Samples

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

値 A は 0.0 〜 1.0 までの範囲で制限。

値 B は 0.0 〜 3.0 までの範囲で制限。

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

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

シェーダー名:SH_greyscale_B

参考動作:Shader - Greyscale - Another Version

OpenGL-ES_50px_May16 WebGL_50px_June16

( MacBook Pro OS X El Capitan + Safari 11601.7.7 で正常に動作せず )

Vertex Shader

 
attribute vec3 in_Position;     // (x,y,z)
attribute vec2 in_TextureCoord; // (u,v)
// 今回、頂点カラーは無視しています、必要な場合は追加
varying vec2 v_vTexcoord;
varying vec4 v_vColour;

void main()
{
    vec4 pos    = vec4(in_Position, 1.0);
    mat4 GMW    = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION];
    gl_Position = GMW * pos;
    v_vTexcoord = in_TextureCoord;
}
 

Fragment Shader

 
varying vec2 v_vTexcoord;

uniform float fadeA;
uniform float fadeB;

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

ユーザ定義関数 Init_GreyscaleShaderB

///Init_GreyscaleShaderB();
draw_set_font(font0);
var a,b,c,d,e;
a = SH_greyscale_B;
    if ( !shader_is_compiled(a) ) {
       b = "ur hardware ain't support shader - SH_greyscale_B";
       show_message(b);
    }
    else{
       /* for Shaders */
       b = "fadeA";
       c = "fadeB";
       d = 1.0;//Maximum value with A
       e = 3.0;//Maximum value with B
       Uni_grey_FA = shader_get_uniform(a, b);
       Var_grey_FA = d;
       Uni_grey_FB = shader_get_uniform(a, c);
       Var_grey_FB = e;
       
       Max_A       = d;
       Max_B       = e;
       MinAB       = 0.0;
       
       /* instance Variables For a Surface */
       Surf        = noone;
       /* instance Variables For Debug use */
       Debug       = true;
    };
 

ユーザ定義関数 Draw_SetSurface

///Draw_SetSurface();
var s = Surf;
if !surface_exists(s){ /* create surface */
    var w,h;
    w    = room_width;
    h    = room_height;
    Surf = surface_create(w,h);
    surface_set_target(Surf);
    {
        /* draw to room background */
        draw_clear_alpha(c_yellow, 1);
        var v,z;
        v    = 150;
        z[2] = c_green;
        z[1] = c_red;
        z[0] = c_blue;
            for (var i=0; i<3; i++){
                draw_set_colour(z[i]);
                draw_rectangle(0,h-v,w,h,false);
                v -= 50;
            };
        /* draw to surface with sprites */
        var a,b;
        a = banners;
        b = sprite_get_height(a);
            for (var i=0; i<3; i++) {
                draw_sprite(a,i, 0,b*i);
            };
    };
    surface_reset_target();
}
else{
    draw_surface(s,0,0);/* draw default */
};
 

ユーザ定義関数 DrawGUI_Greyscale_B

///DrawGUI_Greyscale_B();
if Debug {
    var a,b,c,d,e;
    a = SH_greyscale_B;
    b = Var_grey_FA;
    c = Var_grey_FB;
    d = application_surface;
    shader_set(a);
        {
        shader_set_uniform_f(Uni_grey_FA , b);
        shader_set_uniform_f(Uni_grey_FB , c);
        draw_surface(d, 0,0);
        };
    shader_reset();
};
 

ユーザ定義関数 DrawGUI_Debug_Status

///DrawGUI_Debug_Status();
/* Check the keys */
var a,b,c,d;
a = Var_grey_FA;
b = Var_grey_FB;
c = 0.02;
d = 0.1;
    if (keyboard_check(ord('Q')) and a < Max_A) a += c;
    if (keyboard_check(ord('A')) and a > MinAB) a -= c;
    if (keyboard_check(ord('W')) and b < Max_B) b += d;
    if (keyboard_check(ord('S')) and b > MinAB) b -= d;
    if keyboard_check_pressed(vk_space) Debug = !Debug;

/* show normal messages */
var e,f,g,h;
e = 90;                // x-position
f = (room_height >> 1);// y-position
g = "Greyscale_Another_Version";
h = "Press Spacekey : Toggle render target";
draw_set_colour(c_white);
draw_text(e,  f,    g);
draw_text(20, f+50, h);

/* Debug messages */
e  = 50;              // x-position
f += 120;             // y-position
g  = "press Q|A keys... Var_grey_FA = ";
h  = "press W|S keys... Var_grey_FB = ";
draw_set_colour(c_black);
draw_text(e, f,    g + string(a) );
draw_text(e, f+40, h + string(b) );

/* finalize */
Var_grey_FA = a;
Var_grey_FB = b;
 

イベント処理

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

Create Event

///Init
Init_GreyscaleShaderB();

Draw Event

///Draw
Draw_SetSurface();

Draw GUI Event

///DrawGUI
DrawGUI_Greyscale_B();
DrawGUI_Debug_Status();

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

Draw イベントで描画した画面を DrawGUI で シェーダを使いグレースケール化してレンダーしています。シェーダで application_surface 全体を対象にしてレンダリングする場合は DrawGUI のタイミングで描画するのが無難。




次へ

前へ