Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Your first 2D shader

はじめに

Shaders are special programs that execute on the GPU and are used for rendering graphics. All modern rendering is done with shaders. For a more detailed description of what shaders are please see What are shaders.

このチュートリアルでは、頂点関数とフラグメント関数の両方を使用してシェーダーを作成するプロセスを順を追って説明し、シェーダープログラムを作成する実用的な側面に焦点を当てます。 このチュートリアルは、シェーダーの初心者を対象にしています。

注釈

シェーダーの作成経験があり、Godotでのシェーダーの動作の概要を探しているだけの場合は、シェーディングリファレンス を参照してください。

セットアップ

CanvasItem shaders are used to draw all 2D objects in Godot, while Spatial shaders are used to draw all 3D objects.

In order to use a shader it must be attached inside a Material which must be attached to an object. Materials are a type of Resource. To draw multiple objects with the same material, the material must be attached to each object.

All objects derived from a CanvasItem have a material property. This includes all GUI elements, Sprite2Ds, TileMaps, MeshInstance2Ds etc. They also have an option to inherit their parent's material. This can be useful if you have a large number of nodes that you want to use the same material.

To begin, create a Sprite2D node. You can use any CanvasItem, so long as it is drawing to the canvas, so for this tutorial we will use a Sprite2D, as it is the easiest CanvasItem to start drawing with.

インスペクタで、"Texture"の横にある[空]をクリックして[読込み]を選択し、”Icon.png"を選択します。 新しいプロジェクトの場合、これはGodotアイコンです。 ビューポートにアイコンが表示されます。

次に、インスペクタのCanvasItemセクションの下を見て、「Material」の横をクリックし、「新規 ShaderMaterial」を選択します。 これにより、新しいマテリアルリソースが作成されます。 表示される球をクリックします。 Godotは現在、CanvasItemシェーダーとSpatialシェーダーのどちらを記述しているかを認識せず、Spatialシェーダーの出力をプレビューします。 したがって、表示されているのは、デフォルトのSpatialシェーダーの出力です。

Click beside "Shader" and select "New Shader". Finally, click on the shader you just created and the shader editor will open. You are now ready to begin writing your first shader.

最初のキャンバスアイテム(CanvasItem)シェーダー

Godotでは、すべてのシェーダーは、シェーダーのタイプを指定する行で始まります。 次の形式を使用します:

shader_type canvas_item;

CanvasItemシェーダーを記述しているため、最初の行で canvas_item を指定します。 すべてのコードは、この宣言の下に配置されます。

この行は、どの組み込み変数と関数を提供するかをエンジンに伝えます。

Godotでは、3つの関数をオーバーライドして、シェーダーの動作を制御できます。vertexfragment、および light。 このチュートリアルでは、頂点(vertex)関数とフラグメント(fragment)関数の両方を使用してシェーダーを作成する方法を説明します。 ライト(light)関数は、頂点関数やフラグメント関数よりもかなり複雑なので、ここでは説明しません。

最初のフラグメント関数

The fragment function runs for every pixel in a Sprite2D and determines what color that pixel should be.

They are restricted to the pixels covered by the Sprite2D, that means you cannot use one to, for example, create an outline around a Sprite2D.

最も基本的なフラグメント関数は、すべてのピクセルに単一の色を割り当てること以外は何もしません。

We do so by writing a vec4 to the built-in variable COLOR. vec4 is shorthand for constructing a vector with 4 numbers. For more information about vectors see the Vector math tutorial. COLOR is both an input variable to the fragment function and the final output from it.

void fragment(){
  COLOR = vec4(0.4, 0.6, 0.9, 1.0);
}
../../../_images/blue-box.png

おめでとう! できました。 Godotで最初のシェーダーの作成に成功しました。

それでは、もっと複雑にしましょう。

There are many inputs to the fragment function that you can use for calculating COLOR. UV is one of them. UV coordinates are specified in your Sprite2D (without you knowing it!) and they tell the shader where to read from textures for each part of the mesh.

フラグメント関数では UV からしか読み取ることができませんが、他の関数で使用したり、値を COLOR に直接割り当てることができます。

UV は、左から右、上から下で0~1の間で変化します。

../../../_images/iconuv.png
void fragment() {
  COLOR = vec4(UV, 0.5, 1.0);
}
../../../_images/UV.png

TEXTURE ビルトインを使用する

When you want to adjust a color in a Sprite2D you cannot just adjust the color from the texture manually like in the code below.

void fragment(){
  //this shader will result in an all white rectangle
  COLOR.b = 1.0;
}

The default fragment function reads from a texture and displays it. When you overwrite the default fragment function, you lose that functionality, so you have to implement it yourself. You read from textures using the texture function. Certain nodes, like Sprite2Ds, have a dedicated texture variable that can be accessed in the shader using TEXTURE. Use it together with UV and texture to draw the Sprite2D.

void fragment(){
  COLOR = texture(TEXTURE, UV); //read from texture
  COLOR.b = 1.0; //set blue channel to 1.0
}
../../../_images/blue-tex.png

Uniform入力

Uniform入力は、シェーダー全体で同一のデータを、シェーダーに渡すために使用されます。

Uniformを使用するには、シェーダーの上部で次のように定義します:

uniform float size;

使用法の詳細については、シェーディング言語ドキュメント を参照してください。

Add a uniform to change the amount of blue in our Sprite2D.

uniform float blue = 1.0; // you can assign a default value to uniforms

void fragment(){
  COLOR = texture(TEXTURE, UV); //read from texture
  COLOR.b = blue;
}

Now you can change the amount of blue in the Sprite2D from the editor. Look back at the Inspector under where you created your shader. You should see a section called "Shader Param". Unfold that section and you will see the uniform you just declared. If you change the value in the editor, it will overwrite the default value you provided in the shader.

コードからシェーダーを操作する

You can change uniforms from code using the function set_shader_parameter() which is called on the node's material resource. With a Sprite2D node, the following code can be used to set the blue uniform.

var blue_value = 1.0
material.set_shader_parameter("blue", blue_value)

uniformの名前は文字列であることに注意してください。文字列は、スペルや大文字小文字を含め、シェーダーでの記述方法と正確に一致する必要があります。

最初の頂点関数

フラグメント関数ができたので、頂点関数を書きましょう。

頂点関数を使用して、各頂点が画面のどこに出現するかを計算します。

頂点関数の最も重要な変数は VERTEX です。最初はモデルの頂点座標を指定しますが、実際にそれらの頂点を描画する場所を決定するために書き込むこともできます。VERTEX は、ローカル空間で最初に表示される vec2 です(つまり、カメラ、ビューポート、または親ノードに関連しません)。

VERTEX に直接追加することにより、頂点をオフセットできます。

void vertex() {
  VERTEX += vec2(10.0, 0.0);
}

Combined with the TIME built-in variable, this can be used for basic animation.

void vertex() {
  // Animate Sprite2D moving in big circle around its location
  VERTEX += vec2(cos(TIME)*100.0, sin(TIME)*100.0);
}

結論

コアでは、シェーダーはこれまで見てきたことを実行し、VERTEXCOLOR を計算します。これらの変数に値を割り当てるためのより複雑な数学的戦略を考え出すのはあなた次第です。

インスピレーションを得るには、Shadertoy`The Book of Shaders <https://thebookofshaders.com>`_などのより高度なシェーダーチュートリアルをいくつか見てください。