Up to date

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

Guide de style des shaders

Ce guide de style liste les standards pour écrire du GDScript élégant. Le but est d'encourager l'écriture de code propre et lisible ainsi que de promouvoir l'uniformité au travers des projets, les discussions et les tutoriels. Nous espérons que cela encourage le développement d'outil auto-formatage.

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.

Les guides de style ne sont pas conçus comme des livres de règles rigides. Parfois, il se peut que vous ne puissiez pas appliquer certaines des règles ci-dessous. Lorsque cela se produit, utilisez votre jugement et demandez à vos collègues développeurs de vous donner leur avis.

En général, garder votre code consistant dans vos projets et au sein de votre équipe est plus important que de suivre ce guide à la lettre.

Note

L'éditeur de script intégré dans Godot utilise beaucoup de ces standards par défaut. Laissez-le vous aider.

Voici un exemple de classe complet basé sur ces lignes directrices :

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;
}

Formatage

Encodage et caractères spéciaux

  • Utilisez le saut de ligne (LF) pour terminer les lignes, et non CRLF ou CR. (éditeur par défaut)

  • Utilisez un caractère de saut de ligne à la fin de chaque fichier. (éditeur par défaut)

  • Utilisez l'encodage UTF-8 sans indicateur d'ordre d'octet. (éditeur par défaut)

  • Utilisez Tabs au lieu d'espaces pour l'indentation. (éditeur par défaut)

Indentation

Chaque niveau d'indentation doit être supérieur d'une tabulation au bloc qui le contient.

Bon :

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

Mauvais :

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

Utiliser 2 niveaux d'indentations pour distinguer les suites de lignes des blocs de code réguliers.

Bon :

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

Mauvais :

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

Retours de ligne et lignes vierges

Pour une règle générale d'indentation, suivez la règle "1TBS Style" qui recommande de placer l'accolade associée à une instruction de contrôle sur la même ligne. Utilisez toujours des accolades pour les instructions, même si elles ne couvrent qu'une seule ligne. Cela les rend plus faciles à remanier et évite les erreurs lors de l'ajout de lignes supplémentaires à une instruction if ou similaire.

Bon :

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

Mauvais :

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

Lignes vides

Entourez les définitions de fonctions d'une (et d'une seule) ligne vierge :

void do_something() {
    // ...
}

void fragment() {
    // ...
}

Utilisez une (et une seule) ligne blanche à l'intérieur des fonctions pour séparer les sections logiques.

Longueur de la ligne

Gardez chaque ligne de code en dessous de 100 caractères.

Si vous le pouvez, essayez de ne pas dépasser 80 caractères par ligne. Cela permet de lire le code sur de petits écrans et avec deux scripts ouverts côte à côte dans un éditeur de texte externe. Par exemple, lorsqu'il s'agit d'une révision différentielle.

Une Instruction par ligne

Ne combinez jamais plusieurs déclarations sur une seule ligne.

Bon :

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

Mauvais :

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

La seule exception à cette règle est l'opérateur ternaire :

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

Espace de commentaires

Les commentaires normaux doivent commencer avec un espace, mais pas les commentaires qui désactivent du code. Cela aide à différencier les commentaires textes du code désactivé.

Bon :

// This is a comment.
//return;

Mauvais :

//This is a comment.
// return;

N'utilisez pas la syntaxe des commentaires multilignes si votre commentaire peut tenir sur une seule ligne :

/* This is another comment. */

Note

Dans l'éditeur de shaders, pour faire du code sélectionné un commentaire (ou le décommenter), appuyez sur Ctrl + K. Cette fonction permet d'ajouter ou de supprimer // au début des lignes sélectionnées.

Espaces

Utilisez toujours un espace autour des opérateurs et après les virgules. Évitez également les espaces superflus dans les appels de fonction.

Bon :

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

Mauvais :

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

Ne pas utiliser d'espaces pour aligner verticalement les expressions :

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

Nombres à virgule flottante

Spécifiez toujours au moins un chiffre pour la partie entière et la partie fractionnaire. Cela permet de distinguer plus facilement les nombres à virgule flottante des nombres entiers, ainsi que de distinguer les nombres supérieurs à 1 de ceux qui sont inférieurs à 1.

Bon :

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

Mauvais :

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

Accès aux membres d'un vecteur

Utilisez r, g, b, et a pour accéder aux membres d'un vecteur s'il contient une couleur. Si le vecteur contient autre chose qu'une couleur, utilisez x, y, z, et w. Cela permet à ceux qui lisent votre code de mieux comprendre ce que les données sous-jacentes représentent.

Bon :

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

Mauvais :

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

Conventions de nommage

Ces conventions de nommage suivent le style du moteur Godot. Si vous ne les respectez pas, votre code se détachera des conventions de nommage existantes, ce qui entraînera un code incohérent.

Fonctions et Variables

Utiliser le snake_case pour nommer les fonctions et variables :

void some_function() {
     float some_variable = 0.5;
}

Constantes

Écrivez les constantes avec CONSTANT_CASE, c'est-à-dire en majuscules avec un trait de soulignement (_) pour séparer les mots :

const float GOLDEN_RATIO = 1.618;

Preprocessor directives

Shader preprocessor directives should be written in CONSTANT__CASE. Directives should be written without any indentation before them, even if nested within a function.

To preserve the natural flow of indentation when shader errors are printed to the console, extra indentation should not be added within #if, #ifdef or #ifndef blocks:

Bon :

#define HEIGHTMAP_ENABLED

void fragment() {
    vec2 position = vec2(1.0, 2.0);

#ifdef HEIGHTMAP_ENABLED
    sample_heightmap(position);
#endif
}

Mauvais :

#define heightmap_enabled

void fragment() {
    vec2 position = vec2(1.0, 2.0);

    #ifdef heightmap_enabled
        sample_heightmap(position);
    #endif
}

Ordre du code

Nous suggérons d'organiser le code des shaders de cette façon :

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

Nous avons optimisé l'ordre pour rendre le code plus simple à lire de haut en bas, afin d'aider les développeurs à comprendre comment le code fonctionne la première fois qu'ils le lisent, et pour éviter les erreurs liées à l'ordre de déclaration des variables.

Cet ordre de code suit deux règles générales :

  1. Les métadonnées et les propriétés d'abord, puis les méthodes.

  2. Le mot "public" vient avant le mot "privé". Dans le contexte d'une langue de type shader, "public" fait référence à ce qui est facilement ajustable par l'utilisateur (les uniformes).

Variables locales

Déclarez les variables locales le plus près possible de leur première utilisation. Il est ainsi plus facile de suivre le code, sans avoir à trop le faire défiler pour retrouver l'endroit où la variable a été déclarée.