| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 | .. _doc_shaders_style_guide:Shaders style guide===================This style guide lists conventions to write elegant shaders. The goal is toencourage writing clean, readable code and promote consistency across projects,discussions, and tutorials. Hopefully, this will also support the development ofauto-formatting tools.Since the Godot shader language is close to C-style languages and GLSL, thisguide is inspired by Godot's own GLSL formatting. You can view examples ofGLSL files in Godot's source code`here <https://github.com/godotengine/godot/blob/master/drivers/gles3/shaders/>`__.Style guides aren't meant as hard rulebooks. At times, you may not be able toapply some of the guidelines below. When that happens, use your best judgment,and ask fellow developers for insights.In general, keeping your code consistent in your projects and within your team ismore important than following this guide to a tee... note:: 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:.. code-block:: glsl    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.gdshader    uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;    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;    }Formatting----------Encoding and special characters~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* Use line feed (**LF**) characters to break lines, not CRLF or CR. *(editor default)** Use one line feed character at the end of each file. *(editor default)** Use **UTF-8** encoding without a `byte order mark <https://en.wikipedia.org/wiki/Byte_order_mark>`_. *(editor default)** Use **Tabs** instead of spaces for indentation. *(editor default)*Indentation~~~~~~~~~~~Each indent level should be one tab greater than the block containing it.**Good**:.. code-block:: glsl    void fragment() {        COLOR = vec3(1.0, 1.0, 1.0);    }**Bad**:.. code-block:: glsl    void fragment() {            COLOR = vec3(1.0, 1.0, 1.0);    }Use 2 indent levels to distinguish continuation lines fromregular code blocks.**Good**:.. code-block:: glsl    vec2 st = vec2(            atan(NORMAL.x, NORMAL.z),            acos(NORMAL.y));**Bad**:.. code-block:: glsl    vec2 st = vec2(        atan(NORMAL.x, NORMAL.z),        acos(NORMAL.y));Line breaks and blank lines~~~~~~~~~~~~~~~~~~~~~~~~~~~For a general indentation rule, follow`the "1TBS Style" <https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)>`_which recommends placing the brace associated with a control statement on thesame 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 toan ``if`` statement or similar.**Good**:.. code-block:: glsl    void fragment() {        if (true) {            // ...        }    }**Bad**:.. code-block:: glsl    void fragment()    {        if (true)            // ...    }Blank lines~~~~~~~~~~~Surround function definitions with one (and only one) blank line:.. code-block:: glsl    void do_something() {        // ...    }    void fragment() {        // ...    }Use one (and only one) blank line inside functions to separate logical sections.Line length~~~~~~~~~~~Keep individual lines of code under 100 characters.If you can, try to keep lines under 80 characters. This helps to read the codeon small displays and with two shaders opened side-by-side in an external texteditor. For example, when looking at a differential revision.One statement per line~~~~~~~~~~~~~~~~~~~~~~Never combine multiple statements on a single line.**Good**:.. code-block:: glsl    void fragment() {        ALBEDO = vec3(1.0);        EMISSION = vec3(1.0);    }**Bad**:.. code-block:: glsl    void fragment() {        ALBEDO = vec3(1.0); EMISSION = vec3(1.0);    }The only exception to that rule is the ternary operator:.. code-block:: glsl   void fragment() {        bool should_be_white = true;        ALBEDO = should_be_white ? vec3(1.0) : vec3(0.0);    }Comment spacing~~~~~~~~~~~~~~~Regular comments should start with a space, but not code that you comment out.This helps differentiate text comments from disabled code.**Good**:.. code-block:: glsl    // This is a comment.    //return;**Bad**:.. code-block:: glsl    //This is a comment.    // return;Don't use multiline comment syntax if your comment can fit on a single line:.. code-block:: glsl    /* This is another comment. */.. note::   In the shader editor, to make the selected code a comment (or uncomment it),   press :kbd:`Ctrl + K`. This feature adds or removes ``//`` at the start of   the selected lines.Documentation comments~~~~~~~~~~~~~~~~~~~~~~Use the following format for documentation comments above uniforms, with **two**leading asterisks (``/**``) and follow-up asterisks on every line:.. code-block:: glsl    /**     * This is a documentation comment.     * These lines will appear in the inspector when hovering the shader parameter     * named "Something".     * You can use [b]BBCode[/b] [i]formatting[/i] in the comment.     */    uniform int something = 1;These comments will appear when hovering a property in the inspector. If youdon't wish the comment to be visible in the inspector, use the standard commentsyntax instead (``// ...`` or ``/* ... */`` with only one leading asterisk).Whitespace~~~~~~~~~~Always use one space around operators and after commas. Also, avoid extraneous spacesin function calls.**Good**:.. code-block:: glsl    COLOR.r = 5.0;    COLOR.r = COLOR.g + 0.1;    COLOR.b = some_function(1.0, 2.0);**Bad**:.. code-block:: glsl    COLOR.r=5.0;    COLOR.r = COLOR.g+0.1;    COLOR.b = some_function (1.0,2.0);Don't use spaces to align expressions vertically:.. code-block:: glsl    ALBEDO.r   = 1.0;    EMISSION.r = 1.0;Floating-point numbers~~~~~~~~~~~~~~~~~~~~~~Always specify at least one digit for both the integer and fractional part. Thismakes it easier to distinguish floating-point numbers from integers, as well asdistinguishing numbers greater than 1 from those lower than 1.**Good**:.. code-block:: glsl    void fragment() {        ALBEDO.rgb = vec3(5.0, 0.1, 0.2);    }**Bad**:.. code-block:: glsl    void fragment() {        ALBEDO.rgb = vec3(5., .1, .2);    }Accessing vector members------------------------Use ``r``, ``g``, ``b``, and ``a`` when accessing a vector's members if itcontains a color. If the vector contains anything else than a color, use ``x``,``y``, ``z``, and ``w``. This allows those reading your code to betterunderstand what the underlying data represents.**Good**:.. code-block:: glsl    COLOR.rgb = vec3(5.0, 0.1, 0.2);**Bad**:.. code-block:: glsl    COLOR.xyz = vec3(5.0, 0.1, 0.2);Naming conventions------------------These naming conventions follow the Godot Engine style. Breaking these will makeyour code clash with the built-in naming conventions, leading to inconsistentcode.Functions and variables~~~~~~~~~~~~~~~~~~~~~~~Use snake\_case to name functions and variables:.. code-block:: glsl   void some_function() {        float some_variable = 0.5;   }Constants~~~~~~~~~Write constants with CONSTANT\_CASE, that is to say in all caps with anunderscore (\_) to separate words:.. code-block:: glsl    const float GOLDEN_RATIO = 1.618;Preprocessor directives~~~~~~~~~~~~~~~~~~~~~~~:ref:`doc_shader_preprocessor` directives should be written in CONSTANT__CASE.Directives should be written without any indentation before them, even ifnested within a function.To preserve the natural flow of indentation when shader errors are printed tothe console, extra indentation should **not** be added within ``#if``,``#ifdef`` or ``#ifndef`` blocks:**Good**:.. code-block:: glsl    #define HEIGHTMAP_ENABLED    void fragment() {        vec2 position = vec2(1.0, 2.0);    #ifdef HEIGHTMAP_ENABLED        sample_heightmap(position);    #endif    }**Bad**:.. code-block:: glsl    #define heightmap_enabled    void fragment() {        vec2 position = vec2(1.0, 2.0);        #ifdef heightmap_enabled            sample_heightmap(position);        #endif    }Applying formatting automatically---------------------------------To automatically format shader files, you can use`clang-format <https://clang.llvm.org/docs/ClangFormat.html>`__ on one or several``.gdshader`` files, as the syntax is close enough to a C-style language.However, the default style in clang-format doesn't follow this style guide,so you need to save this file as ``.clang-format`` in your project's root folder:.. code-block:: yaml    BasedOnStyle: LLVM    AlignAfterOpenBracket: DontAlign    AlignOperands: DontAlign    AlignTrailingComments:    Kind: Never    OverEmptyLines: 0    AllowAllParametersOfDeclarationOnNextLine: false    AllowShortFunctionsOnASingleLine: Inline    BreakConstructorInitializers: AfterColon    ColumnLimit: 0    ContinuationIndentWidth: 8    IndentCaseLabels: true    IndentWidth: 4    InsertBraces: true    KeepEmptyLinesAtTheStartOfBlocks: false    RemoveSemicolon: true    SpacesInLineCommentPrefix:    Minimum: 0 # We want a minimum of 1 for comments, but allow 0 for disabled code.    Maximum: -1    TabWidth: 4    UseTab: AlwaysWhile in the project root, you can then call ``clang-format -i path/to/shader.gdshader``in a terminal to format a single shader file, or ``clang-format -i path/to/folder/*.gdshader``to format all shaders in a folder.Code order----------We suggest to organize shader code this way:.. code-block:: glsl    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() functionWe optimized the order to make it easy to read the code from top to bottom, tohelp developers reading the code for the first time understand how it works, andto avoid errors linked to the order of variable declarations.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 iteasier to follow the code, without having to scroll too much to find where thevariable was declared.
 |