シェーダーは、GPUで実行される、描画の並列処理を記述するためのプログラムです。
CPUで実行するためのGDScriptとは別物。
GDScriptはPythonベースですが、シェーダーはC言語ベースの異なる言語です。
シェーダーの種類(shader_type)には、spacial(3D用), canvas_item(2D用), particles(パーティクルシステム用)の3種類があります。まずは canvas_item を使いこなせるようになりましょう。
CPUで実行する、横width, 縦heightの矩形領域を赤色に設定する処理をC言語で書くと、以下のようなコードになります。
for文で、矩形領域内の座標(x, y)のピクセルを順番に処理。
set_col() 関数で、座標(x, y)のピクセルの色を red に設定するというイメージです。
for(int x = 0; x < width; x++) {
for(int y = 0; y < height; y++) {
set_col(x, y, red);
}
}
シェーダーの世界では、上記のようなfor文が無くなります。
並列に実行される、描画領域内の各ピクセルにおける処理のみを記述するので、以下のようなコードになります。
// function called for each pixel
void fragment() {
COLOR = red;
}
COLORは、ピクセルの色を表す変数。
redは、R,G,B, アルファで構成される4次元ベクトルで、
red = vec4(1.0, 0.0, 0.0, 1.0);
という値です。
fragment() 関数は、プロセッサー関数と呼ばれるもので、他に vertex() 関数、light() 関数という二人の仲間がいます。一番よく使うのは、色の描画処理を行う fragment() 関数なので、まずは、この関数と仲良くなりましょう。
シェーダーを使うには、ColorRectなどのnodeのインスペクタで、Materialに「新規 Shader Material」を選択。
shaderが「空(empty)」となっているところに、「新規 Shader」を選択すると、コード編集画面が開きます。
英語版ですが、以下の操作動画がわかりやすいです(kids can codeより引用)。
シェーダーのコードを書いてみましょう。
shader_type canvas_item;
void fragment() {
COLOR = vec4(UV.x, UV.y, 0.5, 1.0);
}
これを実行すると、以下のようにColorRectノードの色が変わります。
(UV.x, UV.y)は「描画領域の左上端を(0, 0)、右下端を(1, 1)」とみなした座標系における座標で、正規化座標と呼ばれるものです。正規化座標を使うことで、実際の描画領域のサイズが異なる場合でも、同じコードを利用できます。
上記のシェーダーコードでは、RGBのRをUV.xにしているので、右に行くほど赤くなります。
GはUV.yなので、下に行くほど緑になります。Bは0.5の固定値なので、どこでも一定です。
vec4(UV.x, UV.y, 0.5, 1.0) の最後要素の1.0は、アルファ値という透明度を表すものです。
1.0は不透明、0.0は透明になります。
私が作成したペンライトアプリには、ライトを点滅させるモードがあります。
これを実現しているのは、次のシェーダーコードです。
shader_type canvas_item;
void fragment() {
vec3 red = vec3(1.0, 0.0, 0.0);
float gain = abs(sin(5.*TIME));
if(gain > 0.4) gain = 1.0;
COLOR = vec4(red * gain, 1.0);
}
TIMEは経過時間ごとに与えられる秒数です。
赤色の度合いをsin関数の絶対値を取って、0.0 〜1.0 の範囲で、時間変化させています。
光っている時間は、しっかり赤色が見えるようにしたいので、0.4以上の時は赤色の度合いを 1.0 に切り上げるようにしています。
もう一つのグラデーションモードも、30行ほどのシェーダーコードで実現しています。
皆さんも、自分なりのペンライトの光らせ方をさせてみると、よい練習問題になるとかもしれません。
ぜひシェーダーで遊んでみてください!
楽しいですよ〜
ペンライト ぴかっち
■Godot入門記事
1.
Godot EngineでAndroid/iOSアプリを同時開発しよう!2.
Godot Engineおすすめ学習コース3.
Godot Engineの入門チュートリアルが終わったら4.
シェーダーで遊ぼう!