GameMaker:Studio Shader コントラスト

 shader   contrast   GLSL_ES 

フリーで配布されていたシェーダのサンプルがかなりごちゃごちゃしていたので、整理してみた。

コントラストを調整するシェーダ。

元となったサンプルではオブジェクトを4つ使っていたため、それを一つのオブジェクトへまとめ、イベントも

    1. Create
    2. Step
    3. Draw
    4. DrawGUI

上記四つのイベントに納めた。コードで冗長な部分はざっくり削除し無駄な変数定義を全て排除。

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

参考(YoYoGames MarketPlace):xygthop3’s Shader Resources

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

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

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

シェーダー名:shd_bright_contrast

Vertex shader

attribute vec3 in_Position;
attribute vec2 in_TextureCoord;

varying   vec2 v_texcoord;

void main()
{
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * vec4(in_Position, 1.0);
    v_texcoord = in_TextureCoord;
}

void main() は頂点シェーダで最初に処理される関数。

gl_Position は GLSL のビルトイン( 組み込み変数 ) で vec4 変数。頂点座標を出力して受け取る変数。

v_texcoord はテクスチャの情報を受け取るビルトイン。テクスチャのUV座標を扱う。

u_texcoord もある。

WebGL/GLSL ES でテクスチャとして利用できる画像における制約は

  1. 画像の縦横ピクセル数がニの累乗(pow2)であること
  2. 長方形であること(正方形も長方形に含まれます)

正方形である必要はなく、縦横サイズがニの累乗であるかにだけ気を使えば良い。

Fragment shader

varying vec2  v_texcoord;

uniform float brightness_amount;
uniform float contrast_amount;

void main()
{ 
    vec4 colour = texture2D(gm_BaseTexture,v_texcoord);
    gl_FragColor = vec4( (colour.rgb+brightness_amount) * (1.0+contrast_amount)/1.0, colour.a);
}

ユーザ定義関数 init_create_surface(x, y);

///init_create_surface(xview, yview);
surf               = surface_create(argument0, argument1);
view_surface_id[0] = surf;

ユーザ定義関数 Init_ContrastShader();

///Init_ContrastShader();
draw_set_color(c_white);
// shd_bright_contrast はシェーダー名
uni_brightness_amount = shader_get_uniform(shd_bright_contrast,"brightness_amount");
var_brightness_amount = 0;

uni_contrast_amount   = shader_get_uniform(shd_bright_contrast,"contrast_amount");
var_contrast_amount   = 0;

shader_enabled        = true;
full_screen_effect    = true;

GML の shader_get_uniform 関数はシェーダの持つ変数と値を共有するためのもの。

shader_get_uniform(シェーダ名 ,"シェーダで uniform として確保された変数名");

GML で指定された変数 uni_brightness_amount は シェーダから渡された値を受け取るためだけの変数。これは普通の変数ではなく、シェーダと値を共有するための変数であり、一種 C 言語のポインタみたいなものかもしれない。シェーダとGMLで値を橋渡しする役割を果たす。

var_brightness_amount は STEP イベントによって変更された値が格納される。

そしてこの値は DrawGUI Event のタイミングで shader_set_uniform_f() 関数を使ってシェーダ側に値送信される。

shader_set_uniform_f(シェーダとGMLで共有してる値 , GML から指定する値);

以下にまとめると、シェーダ側で確保した変数、GMLでそれを受け取り参照しGML側から値を渡すための関数及び変数、GML側の変数、三つの変数によって値のやり取りが行われている。

この値のやり取りに三つの変数が必要と成る点が手続きを煩雑にしている。

  • シェーダ側で確保された変数
  • GMLからシェーダ側の値を参照し、GMLからシェーダへ値渡しする関数及び変数
  • GML側の変数

Create Event

///Init

    if (!shader_is_compiled(shd_bright_contrast)) {
       show_message("Your hardware doesn't support shader - shd_bright_contrast");
    };

draw_set_font(font0);

Init_ContrastShader();
init_create_surface(view_wview, view_hview);
//------------------------------------------------------------
image_speed       = 0.15;
x                 = view_wview[0]/2;
y                 = 544;
bx                = x;

Step Event

///Keycheck
/*
keyboard_check function, this function is triggered every step 
                                                    ~~~~~~~~~~
*/
var a = vk_anykey;
if keyboard_check(a){
    if (keyboard_check(ord('Q')) and (var_brightness_amount <  1)) {var_brightness_amount += 0.01;};
    if (keyboard_check(ord('A')) and (var_brightness_amount > -1)) {var_brightness_amount -= 0.01;};
    
    if (keyboard_check(ord('W')) and (var_contrast_amount <  1)) {var_contrast_amount += 0.01;};
    if (keyboard_check(ord('S')) and (var_contrast_amount > -1)) {var_contrast_amount -= 0.01;};
};

if keyboard_check_released(a){
    if (keyboard_check_released(vk_shift)){Init_ContrastShader(); view_surface_id[0] = surf;};
    if (keyboard_check_released(vk_space)){
        shader_enabled     = !shader_enabled;
        full_screen_effect = !full_screen_effect;
            if (!full_screen_effect){ view_surface_id[0] = -1; }
            else { view_surface_id[0] = surf };
    };
};

Draw Event

///draw background and sprite
bx--;
draw_background_tiled_ext(bac_level,bx,0,2,2,c_white,1);
draw_sprite(spr_walk, image_index, x, y);

DrawGUI Event

///Set Shader Constant and draw Surface

    if shader_enabled {
        shader_set(shd_bright_contrast);
        shader_set_uniform_f(uni_brightness_amount, var_brightness_amount);
        shader_set_uniform_f(uni_contrast_amount,   var_contrast_amount );
            if full_screen_effect {
                if surface_exists(surf){
                   draw_surface(surf,0,0);
                }
                else{
                   init_create_surface(view_wview, view_hview);
                };
            };
        shader_reset();
    };


draw_text(0,12,"Brightness amount (Q & A to adjust): "+string(var_brightness_amount));
draw_text(0,24,"Contrast amount (W & S to adjust): "+string(var_contrast_amount));

var a;
    if full_screen_effect {
        a = "Spacebar to toggle shader ::: OFF";
    }
    else{
        a = "Spacebar to toggle shader ::: ON";
    };
draw_text(0,60,a);
draw_text(0,72,"Shift key to Reset current values of Shader Palams");




次へ

前へ