Guia de estilo de shaders¶
Este guia de estilo lista convenções para escrever de forma elegante os shaders. O objetivo é encorajar a escrita de código limpo e legível e promover a consistência entre projetos, discussões e tutoriais. Esperamos que isto também apoie o desenvolvimento de ferramentas de formatação automática.
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.
Guias de estilo não são regras. Às vezes, você talvez não poderá aplicar algumas das diretrizes abaixo. Quando isso acontecer, use seu melhor julgamento, e peça opiniões de outros desenvolvedores.
Em geral, manter seu código consistente em seus projetos e em seu time é mais importante que seguir este guia à risca.
Nota
O editor de shader integrado de Godot usa muitas dessas convenções por padrão. Deixa que te ajude.
Aqui está um exemplo completo de shader baseado nestas diretrizes:
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;
}
Formatação¶
Codificação e caracteres especiais¶
Use caracteres line feed (LF) para quebrar linhas, não CRLF ou CR. (padrão do editor)
Use um caractere line feed no final de cada arquivo. (padrão do editor)
Use a codificação UTF-8 sem uma marca de ordem de byte. (padrão do editor)
Use Tabs ao invés de espaços para indentação. (padrão do editor)
Recuo¶
Cada nível de indentação deve ser uma unidade maior que a do bloco que o contém.
Bom:
void fragment() {
COLOR = vec3(1.0, 1.0, 1.0);
}
Ruim:
void fragment() {
COLOR = vec3(1.0, 1.0, 1.0);
}
Use 2 níveis de indentação para distinguir linhas contínuas de blocos de código regulares.
Bom:
vec2 st = vec2(
atan(NORMAL.x, NORMAL.z),
acos(NORMAL.y));
Ruim:
vec2 st = vec2(
atan(NORMAL.x, NORMAL.z),
acos(NORMAL.y));
Quebras de linha e linhas em branco¶
Para uma regra geral de recuo, siga the "1TBS Style" <https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)> _ que recomenda colocar a chave associada a uma instrução de controle na mesma linha. Sempre use colchetes para as declarações, mesmo se elas ocuparem apenas uma linha. Isso os torna mais fáceis de refatorar e evita erros ao adicionar mais linhas a uma instrução `` if`` ou similar.
Bom:
void fragment() {
if (true) {
// ...
}
}
Ruim:
void fragment()
{
if (true)
// ...
}
Linhas em branco¶
Envolva as definições de função com uma (e apenas uma) linha em branco:
void do_something() {
// ...
}
void fragment() {
// ...
}
Use uma (e apenas uma) linha em branco dentro das funções para separar seções lógicas.
Tamanho de linha¶
Mantenha linhas individuais de código abaixo de 100 caracteres.
Se puder, tente manter as linhas com menos de 80 caracteres. Isso ajuda a ler o código em telas pequenas e com dois shaders abertos lado a lado em um editor de texto externo. Por exemplo, ao olhar para uma revisão diferencial.
Uma declaração por linha¶
Never combine multiple statements on a single line.
Bom:
void fragment() {
ALBEDO = vec3(1.0);
EMISSION = vec3(1.0);
}
Ruim:
void fragment() {
ALBEDO = vec3(1.0); EMISSION = vec3(1.0);
}
A única exceção a essa regra é o operador ternário:
void fragment() {
bool should_be_white = true;
ALBEDO = should_be_white ? vec3(1.0) : vec3(0.0);
}
Espaço em branco¶
Use sempre um espaço ao redor dos operadores e depois das vírgulas. Além disso, evite espaços estranhos em chamadas de função.
Bom:
COLOR.r = 5.0;
COLOR.r = COLOR.g + 0.1;
COLOR.b = some_function(1.0, 2.0);
Ruim:
COLOR.r=5.0;
COLOR.r = COLOR.g+0.1;
COLOR.b = some_function (1.0,2.0);
Não use espaços para alinhas expressões verticalmente:
ALBEDO.r = 1.0;
EMISSION.r = 1.0;
Números de ponto flutuante (real)¶
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.
Bom:
void fragment() {
ALBEDO.rgb = vec3(5.0, 0.1, 0.2);
}
Ruim:
void fragment() {
ALBEDO.rgb = vec3(5., .1, .2);
}
Acessando membros do vetor¶
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.
Bom:
COLOR.rgb = vec3(5.0, 0.1, 0.2);
Ruim:
COLOR.xyz = vec3(5.0, 0.1, 0.2);
Convenções de nomes¶
Estas convenções de nomeação seguem o estilo do Godot Engine. Quebrá-las fará com que o seu código fique diferente das convenções de nomeação embutidas, o que deixa o seu código inconsistente.
Funções e variáveis¶
Use snake_case para nomear funções e variáveis:
void some_function() {
float some_variable = 0.5;
}
Constantes¶
Utilize CONSTANT_CASE, com todas as letras maiúsculas e um sublinhado para separas as palavras:
const float GOLDEN_RATIO = 1.618;
Ordem do código¶
Sugerimos organizar o código do shader desta forma:
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
Otimizamos essa ordem pra deixar o código mais fácil de ler de cima pra baixo, para ajudar desenvolvedores lendo o código pela primeira vez a entender como ele funciona, e para evitar erros referentes à ordem da declaração de variáveis.
Essa ordem de código segue duas regras gerais:
Metadados e propriedades primeiro, seguidos por métodos.
"Public" comes before "private". In a shader language's context, "public" refers to what's easily adjustable by the user (uniforms).
Variáveis locais¶
Declare variáveis locais o mais pŕoximo possível de seu primeiro uso. Isto torna mais fácil seguir o código, sem ter que rolar muito para encontrar onde a variável foi declarada.
Espaçamento de comentários¶
Comentários normais devem começar com um espaço, ao contrário de código que você desativa usando um comentário. Isso ajuda a diferenciar comentários em texto de código desativado.
Bom:
Ruim:
Don't use multiline comment syntax if your comment can fit on a single line:
/* This is another comment. */
Nota
No editor de shader, para fazer o código selecionado um comentário (ou descomentar), pressione Ctrl + K. Este recurso adiciona ou remove
//
no início das linhas selecionadas.