Shaders style guide

    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.

    Style guides aren’t meant as hard rulebooks. At times, you may not be able to apply 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 is more 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:

    • 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 . (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:

    1. COLOR = vec3(1.0, 1.0, 1.0);
    2. }

    Bad:

    1. void fragment() {
    2. COLOR = vec3(1.0, 1.0, 1.0);
    3. }

    Use 2 indent levels to distinguish continuation lines from regular code blocks.

    Good:

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

    Bad:

    1. vec2 st = vec2(
    2. acos(NORMAL.y));

    Line breaks and blank lines

    Good:

    1. void fragment() {
    2. if (true) {
    3. // ...
    4. }
    5. }

    Bad:

    1. void fragment()
    2. {
    3. if (true)
    4. // ...
    5. }

    Blank lines

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

    1. void do_something() {
    2. // ...
    3. }
    4. // ...
    5. }

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

    Keep individual lines of code under 100 characters.

    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.

    One statement per line

    Never combine multiple statements on a single line.

    Good:

    Bad:

    1. void fragment() {
    2. ALBEDO = vec3(1.0); EMISSION = vec3(1.0);
    3. }

    The only exception to that rule is the ternary operator:

    1. void fragment() {
    2. bool should_be_white = true;
    3. ALBEDO = should_be_white ? vec3(1.0) : vec3(0.0);
    4. }

    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:

    1. // This is a comment.
    2. //return;

    Bad:

    1. //This is a comment.
    2. // return;

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

    1. /* This is another comment. */

    Note

    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.

    Whitespace

    Good:

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

    Bad:

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

    Don’t use spaces to align expressions vertically:

    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.

    Good:

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

    Bad:

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

    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.

    Good:

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

    Bad:

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

    These naming conventions follow the Godot Engine style. Breaking these will make your code clash with the built-in naming conventions, leading to inconsistent code.

    Functions and variables

    Use snake_case to name functions and variables:

    1. void some_function() {
    2. float some_variable = 0.5;
    3. }

    Constants

    Write constants with CONSTANT_CASE, that is to say in all caps with an underscore (_) to separate words:

    1. const float GOLDEN_RATIO = 1.618;

    We suggest to organize shader code this way:

    1. 01. shader type declaration
    2. 02. render mode declaration
    3. 03. // docstring
    4. 04. uniforms
    5. 05. constants
    6. 06. varyings
    7. 07. other functions
    8. 08. vertex() function
    9. 09. fragment() function
    10. 10. light() function

    We optimized the order to make it easy to read the code from top to bottom, to help developers reading the code for the first time understand how it works, and to 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.

    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.