Color Lerp(線形補間)/マスク

 colour   mix   lerp 

YoYoGames 公式で配布されていたシェーダデモのサンプルを改造したもの( rev.2 )

色の合成効果。キャラクタを明滅させる、イベントに応じた色変化など

スプライトに対して利用した場合、キャラクタの形状で切り抜かれたように「指定された色」で領域が塗りつぶされる。透過率の変化に応じてスプライトが点滅して見える仕組み。

スライダー調整付き・色変更

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

スライダー機能のためにオブジェクトが一つ多い

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



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

Simple Shader Samples

キーボードの Q と A キーで値変更可。

スペースキーでシェーダ切り替え ON・OFF

スライダー調整で描画色の変更が可能

LerpTime の値は 0.0 〜 180.0 までの範囲で制限。

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

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

今回のサンプルではオブジェクトを二つ使っています。一つはスライダーで RGB 色を調整するためのもの。

シェーダー名:SH_LerpColor

参考動作:Shader- Colour Leap -

OpenGL-ES_50px_May16 WebGL_50px_June16

Vertex Shader

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

varying vec2 v_vTexcoord;

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

Fragment Shader

 
varying vec2 v_vTexcoord;

uniform vec4 u_Colour;    // u_Colour.rgba

const float  tone = 255.0;

void main()
{
    vec4 col     = texture2D(gm_BaseTexture, v_vTexcoord);
    gl_FragColor = vec4(mix(col.rgb, u_Colour.rgb / tone, u_Colour.a), col.a);
}
 

ユーザ定義関数 Init_Shader_LerpColor

///Init_Shader_LerpColor();
draw_set_font(font0);
draw_set_colour(c_white);
var a,b;
a = SH_LerpColor;
    if !shader_is_compiled(a) {
        b = "ur hardware ain't support shader - SH_LerpColor";
        show_message(b);
    }
    else{
        b          = "u_Colour";
        
        /* instance variabels for Uniform */
        U_Colour   = shader_get_uniform(a, b);
        LerpTime   = .0;
        Uni_R      = .0; // color tone levels for "ReD"
        Uni_G      = .0; // color tone levels for "GreeN"
        Uni_B      = .0; // color tone levels for "BluE"
        
        /* Instance Variables for Debug */
        VMax       = 180.0;// maximum ( degree value )
        LerpAmount =  20.0;// 0 == slow : 20 == fast
        VMin       =    .0;// minimum
        Shader     =  true;
        Slider     = false;
        SliderID   = noone;
    };
 

ユーザ定義関数 Draw_LerpColor

///Draw_LerpColor();
var a,b,c,d,e, f;
a = SH_LerpColor;
b =     LerpTime;
c =   LerpAmount;
d =         VMax;// 180.
e =         VMin;//    .0

var R,G,B;// 3 Primary colors tone levels vec3(255,255,255)
R = Uni_R;
G = Uni_G;
B = Uni_B;

if Shader {
    b += c;
        if (b > d) b = e;
    
    /* Shader draw start */
    shader_set(a);
    // NOTE: SIN() will give 1 o -1. The -1 will make the image seem "darker"
    f = sin( degtorad(b) );
    shader_set_uniform_f(U_Colour, R,G,B, f);// lerp to WHITE (1,1,1)
    draw_sprite(rb, image_index, x, y); 
    shader_reset();
    
    /* Finalize */
    LerpTime = b;
}
else{
    draw_sprite(rb, image_index, x, y);
};
 

ユーザ定義関数 Draw_ShowStatus

///Draw_ShowStatus();
var a,b,c,d,e,f;
a =  LerpAmount;
b =         1.0;
c =      Shader;
d =    LerpTime;
e =    fps_real;
f = room_height;

/* Check Keys */
if keyboard_check(ord("R")) room_restart();
if keyboard_check(ord("Q"))         a += b;
if keyboard_check(ord("A"))         a -= b;
if keyboard_check_pressed(vk_space) c = !c;
a = clamp(VMin , a , VMax);

/* Debug Status */
draw_text(0,   0, "SH_LerpColor");
draw_text(0,  40, "Real FPS   = " + string(e) );
draw_text(0,  80, "LerpTime   = " + string(d) );
draw_text(0, 120, "LerpAmount = " + string(a) );

draw_text(0,f-80, "Press Q & A Keys : Value UP || Down");
draw_text(0,f-40, "Press Spacekey, toggle Shader");

/* Finalize */
LerpAmount = a;
Shader     = c;
 

ユーザ定義関数 Init_ColourButtons

///Init_ColourButtons();
var a,b,c,d, e;
a = 10;
b = ( (room_height >> 1) - 50 );
c = 40;
d =  3;
/* Create 3 instances */
    for (var i=0; i<d; i++)
    {
        e = ( b + (c*i) );
            with ( instance_create(a,e, button) )
            {
                image_index = i;//  use spread value
                image_speed = 0;// stop the Animation
                    switch (i)
                    {   //    Create an instance Variable
                        case 2:  Colour = "BluE";  break;
                        case 1:  Colour = "GreeN"; break;
                        default: Colour = "ReD";
                    };
            };
    };
 

ユーザ定義関数 Draw_Slider_Function

///Draw_Slider_Function();
var a,b,c,d,e,f, g;
a =   mb_any;
b =   button;   // Clickable Object Name
c =  mouse_x;
d =  mouse_y;
e =   Slider;   // instance varibale with robo.
f = SliderID;   // instance varibale with robo.

/* Check mouse Events */
if (  e & mouse_check_button_released(a) ) { e = false; f = noone; };
if ( !e & mouse_check_button_pressed(a)  ) { e = true;  f = collision_point(c,d,b,-1,1); };


if e {
    if f {
        f.x = c;
        g   = f.xstart + 255;
            if      c < f.xstart f.x = f.xstart;
            else if c > g        f.x = g;
    }
    else  e = false;
};

/* Draw Status */
var h,j,l,m,n,o,p;

with (button)
{
    h =           xstart;
    j =     floor(x - h);
    l =           y + 16;
    m =          h + 255;
    n =           c_gray;
    o = room_width - 100;
    
    draw_line_colour(x,l,m,l,n,n);
    draw_text(o, y, string(j) );
    draw_self();

    p = Colour; 

        switch (p)
        {
            case "BluE":  robo.Uni_B = j; break;
            case "GreeN": robo.Uni_G = j; break;
            default:      robo.Uni_R = j;
        };
};

/* finalize */
Slider   = e;
SliderID = f;
 

イベント処理

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

Create Event

///Init
Init_Shader_LerpColor();
Init_ColourButtons();

Draw Event

///Draw
Draw_Slider_Function();
Draw_LerpColor();
Draw_ShowStatus();

スライダーで色を動的に変えることができる。

Draw_Slider_Function ユーザ定義関数はデバッグなど汎用的利用が可能。

今回のシェーダ効果は当たり判定と組み合わせて、衝突した際にキャラクタースプライトを点滅させたり、特定インスタンスを塗りつぶしたり。

シェーダ使わない GM:Studio 標準機能で同じことができるかは不明だが、シェーダなら悩まず簡単に実装できる。




次へ

前へ