Godot shader language style guide

This style guide lists conventions to write elegant shaders. The goal is to encourage writing clean, readable code and promote consistency across projects, discussions, and tutorials. Hopefully, this will also support the development of auto-formatting tools.

Since the Godot shader language is close to C-style languages and GLSL, this guide is inspired by Godot's own GLSL formatting. You can view an example of a GLSL file in Godot's source code here.

スタイルガイドは、厳密なルールブックを意味するものではありません。時には以下のガイドラインの一部を適用できない場合があります。その場合は、最善であるように判断を下すと共に、仲間の開発者に洞察を求めてください。

一般に、プロジェクト内およびチーム内でコードの一貫性を保つことは、このガイドに完璧に従うよりも重要です。

注釈

Godot's built-in shader editor uses a lot of these conventions by default. Let it help you.

Here is a complete shader example based on these guidelines:

shader_type canvas_item;
// Screen-space shader to adjust a 2D scene's brightness, contrast
// and saturation. Taken from
// https://github.com/godotengine/godot-demo-projects/blob/master/2d/screen_space_shaders/shaders/BCS.shader

uniform float brightness = 0.8;
uniform float contrast = 1.5;
uniform float saturation = 1.8;

void fragment() {
    vec3 c = textureLod(SCREEN_TEXTURE, SCREEN_UV, 0.0).rgb;

    c.rgb = mix(vec3(0.0), c.rgb, brightness);
    c.rgb = mix(vec3(0.5), c.rgb, contrast);
    c.rgb = mix(vec3(dot(vec3(1.0), c.rgb) * 0.33333), c.rgb, saturation);

    COLOR.rgb = c;
}

書式設定

エンコードと特殊文字

  • CRLFやCRではなく、改行(LF)文字を使用して改行します。(エディタのデフォルト)
  • 各ファイルの最後に1つの改行文字を使用します。(エディタのデフォルト)
  • バイトオーダーマークなしでUTF-8エンコーディングを使用します。(エディタのデフォルト)
  • インデントにはスペースの代わりにタブを使用します。(エディタのデフォルト)

インデント

Each indent level should be one tab greater than the block containing it.

良い例:

void fragment() {
    COLOR = vec3(1.0, 1.0, 1.0);
}

悪い例:

void fragment() {
        COLOR = vec3(1.0, 1.0, 1.0);
}

継続行と通常のコードブロックを区別するには、2つのインデントレベルを使用します。

良い例:

vec2 st = vec2(
        atan(NORMAL.x, NORMAL.z),
        acos(NORMAL.y));

悪い例:

vec2 st = vec2(
    atan(NORMAL.x, NORMAL.z),
    acos(NORMAL.y));

改行と空白行

For a general indentation rule, follow the "1TBS Style" which recommends placing the brace associated with a control statement on the same line. Always use braces for statements, even if they only span one line. This makes them easier to refactor and avoids mistakes when adding more lines to an if statement or similar.

良い例:

void fragment() {
    if (true) {
        // ...
    }
}

悪い例:

void fragment()
{
    if (true)
        // ...
}

空白行

Surround function definitions with one (and only one) blank line:

void do_something() {
    // ...
}

void fragment() {
    // ...
}

Use one (and only one) blank line inside functions to separate logical sections.

行の長さ

コードの個々の行を100文字以内に保ちます。

If you can, try to keep lines under 80 characters. This helps to read the code on small displays and with two shaders opened side-by-side in an external text editor. For example, when looking at a differential revision.

1行につき1つのステートメント

Never combine multiple statements on a single line.

良い例:

void fragment() {
    ALBEDO = vec3(1.0);
    EMISSION = vec3(1.0);
}

悪い例:

void fragment() {
    ALBEDO = vec3(1.0); EMISSION = vec3(1.0);
}

その規則の唯一の例外は三項演算子です:

void fragment() {
     bool should_be_white = true;
     ALBEDO = should_be_white ? vec3(1.0) : vec3(0.0);
 }

コメントスペース

通常のコメントはスペースで始まる必要がありますが、コメントアウトしたコードにはスペースは付けません。これにより、テキストコメントと無効化したコードを区別できます。

良い例:

// This is a comment.
//return;

悪い例:

//This is a comment.
// return;

Don't use multiline comment syntax if your comment can fit on a single line:

/* This is another comment. */

注釈

In the shader editor, to make the selected code a comment (or uncomment it), press Ctrl + K. This feature adds or removes // at the start of the selected lines.

スペース

Always use one space around operators and after commas. Also, avoid extraneous spaces in function calls.

良い例:

COLOR.r = 5.0;
COLOR.r = COLOR.g + 0.1;
COLOR.b = some_function(1.0, 2.0);

悪い例:

COLOR.r=5.0;
COLOR.r = COLOR.g+0.1;
COLOR.b = some_function (1.0,2.0);

式を垂直方向に揃えるためにスペースを使用しないでください:

ALBEDO.r   = 1.0;
EMISSION.r = 1.0;

Floating-point numbers

Always specify at least one digit for both the integer and fractional part. This makes it easier to distinguish floating-point numbers from integers, as well as distinguishing numbers greater than 1 from those lower than 1.

良い例:

void fragment() {
    ALBEDO.rgb = vec3(5.0, 0.1, 0.2);
}

悪い例:

void fragment() {
    ALBEDO.rgb = vec3(5., .1, .2);
}

Accessing vector members

Use r, g, b, and a when accessing a vector's members if it contains a color. If the vector contains anything else than a color, use x, y, z, and w. This allows those reading your code to better understand what the underlying data represents.

良い例:

COLOR.rgb = vec3(5.0, 0.1, 0.2);

悪い例:

COLOR.xyz = vec3(5.0, 0.1, 0.2);

命名規則

これらの命名規則は、Godot Engineスタイルに従います。これらを壊すと、コードが組み込みの命名規則と衝突し、コードの一貫性が失われます。

関数と変数

関数と変数に名前を付けるには、snake_caseを使用します:

void some_function() {
     float some_variable = 0.5;
}

定数

CONSTANT_CASEで定数を記述します。つまり、すべて大文字でアンダースコア(_)を使用して単語を区切ります:

const float GOLDEN_RATIO = 1.618;

コードの順序

We suggest to organize shader code this way:

01. shader type declaration
02. render mode declaration
03. // docstring

04. uniforms
05. constants
06. varyings

07. other functions
08. vertex() function
09. fragment() function
10. light() function

順序を最適化して、コードを上から下に読みやすくし、コードを初めて読む開発者がどのように機能するかを理解しやすくし、変数宣言の順序に関連するエラーを回避します。

This code order follows two rules of thumb:

  1. Metadata and properties first, followed by methods.
  2. "Public" comes before "private". In a shader language's context, "public" refers to what's easily adjustable by the user (uniforms).

Local variables

Declare local variables as close as possible to their first use. This makes it easier to follow the code, without having to scroll too much to find where the variable was declared.