shaders_style_guide.rst 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. .. _doc_shaders_style_guide:
  2. Shaders style guide
  3. ===================
  4. This style guide lists conventions to write elegant shaders. The goal is to
  5. encourage writing clean, readable code and promote consistency across projects,
  6. discussions, and tutorials. Hopefully, this will also support the development of
  7. auto-formatting tools.
  8. Since the Godot shader language is close to C-style languages and GLSL, this
  9. guide is inspired by Godot's own GLSL formatting. You can view examples of
  10. GLSL files in Godot's source code
  11. `here <https://github.com/godotengine/godot/blob/master/drivers/gles3/shaders/>`__.
  12. Style guides aren't meant as hard rulebooks. At times, you may not be able to
  13. apply some of the guidelines below. When that happens, use your best judgment,
  14. and ask fellow developers for insights.
  15. In general, keeping your code consistent in your projects and within your team is
  16. more important than following this guide to a tee.
  17. .. note:: Godot's built-in shader editor uses a lot of these conventions
  18. by default. Let it help you.
  19. Here is a complete shader example based on these guidelines:
  20. .. code-block:: glsl
  21. shader_type canvas_item;
  22. // Screen-space shader to adjust a 2D scene's brightness, contrast
  23. // and saturation. Taken from
  24. // https://github.com/godotengine/godot-demo-projects/blob/master/2d/screen_space_shaders/shaders/BCS.gdshader
  25. uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
  26. uniform float brightness = 0.8;
  27. uniform float contrast = 1.5;
  28. uniform float saturation = 1.8;
  29. void fragment() {
  30. vec3 c = textureLod(screen_texture, SCREEN_UV, 0.0).rgb;
  31. c.rgb = mix(vec3(0.0), c.rgb, brightness);
  32. c.rgb = mix(vec3(0.5), c.rgb, contrast);
  33. c.rgb = mix(vec3(dot(vec3(1.0), c.rgb) * 0.33333), c.rgb, saturation);
  34. COLOR.rgb = c;
  35. }
  36. Formatting
  37. ----------
  38. Encoding and special characters
  39. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  40. * Use line feed (**LF**) characters to break lines, not CRLF or CR. *(editor default)*
  41. * Use one line feed character at the end of each file. *(editor default)*
  42. * Use **UTF-8** encoding without a `byte order mark <https://en.wikipedia.org/wiki/Byte_order_mark>`_. *(editor default)*
  43. * Use **Tabs** instead of spaces for indentation. *(editor default)*
  44. Indentation
  45. ~~~~~~~~~~~
  46. Each indent level should be one tab greater than the block containing it.
  47. **Good**:
  48. .. code-block:: glsl
  49. void fragment() {
  50. COLOR = vec3(1.0, 1.0, 1.0);
  51. }
  52. **Bad**:
  53. .. code-block:: glsl
  54. void fragment() {
  55. COLOR = vec3(1.0, 1.0, 1.0);
  56. }
  57. Use 2 indent levels to distinguish continuation lines from
  58. regular code blocks.
  59. **Good**:
  60. .. code-block:: glsl
  61. vec2 st = vec2(
  62. atan(NORMAL.x, NORMAL.z),
  63. acos(NORMAL.y));
  64. **Bad**:
  65. .. code-block:: glsl
  66. vec2 st = vec2(
  67. atan(NORMAL.x, NORMAL.z),
  68. acos(NORMAL.y));
  69. Line breaks and blank lines
  70. ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  71. For a general indentation rule, follow
  72. `the "1TBS Style" <https://en.wikipedia.org/wiki/Indentation_style#Variant:_1TBS_(OTBS)>`_
  73. which recommends placing the brace associated with a control statement on the
  74. same line. Always use braces for statements, even if they only span one line.
  75. This makes them easier to refactor and avoids mistakes when adding more lines to
  76. an ``if`` statement or similar.
  77. **Good**:
  78. .. code-block:: glsl
  79. void fragment() {
  80. if (true) {
  81. // ...
  82. }
  83. }
  84. **Bad**:
  85. .. code-block:: glsl
  86. void fragment()
  87. {
  88. if (true)
  89. // ...
  90. }
  91. Blank lines
  92. ~~~~~~~~~~~
  93. Surround function definitions with one (and only one) blank line:
  94. .. code-block:: glsl
  95. void do_something() {
  96. // ...
  97. }
  98. void fragment() {
  99. // ...
  100. }
  101. Use one (and only one) blank line inside functions to separate logical sections.
  102. Line length
  103. ~~~~~~~~~~~
  104. Keep individual lines of code under 100 characters.
  105. If you can, try to keep lines under 80 characters. This helps to read the code
  106. on small displays and with two shaders opened side-by-side in an external text
  107. editor. For example, when looking at a differential revision.
  108. One statement per line
  109. ~~~~~~~~~~~~~~~~~~~~~~
  110. Never combine multiple statements on a single line.
  111. **Good**:
  112. .. code-block:: glsl
  113. void fragment() {
  114. ALBEDO = vec3(1.0);
  115. EMISSION = vec3(1.0);
  116. }
  117. **Bad**:
  118. .. code-block:: glsl
  119. void fragment() {
  120. ALBEDO = vec3(1.0); EMISSION = vec3(1.0);
  121. }
  122. The only exception to that rule is the ternary operator:
  123. .. code-block:: glsl
  124. void fragment() {
  125. bool should_be_white = true;
  126. ALBEDO = should_be_white ? vec3(1.0) : vec3(0.0);
  127. }
  128. Comment spacing
  129. ~~~~~~~~~~~~~~~
  130. Regular comments should start with a space, but not code that you comment out.
  131. This helps differentiate text comments from disabled code.
  132. **Good**:
  133. .. code-block:: glsl
  134. // This is a comment.
  135. //return;
  136. **Bad**:
  137. .. code-block:: glsl
  138. //This is a comment.
  139. // return;
  140. Don't use multiline comment syntax if your comment can fit on a single line:
  141. .. code-block:: glsl
  142. /* This is another comment. */
  143. .. note::
  144. In the shader editor, to make the selected code a comment (or uncomment it),
  145. press :kbd:`Ctrl + K`. This feature adds or removes ``//`` at the start of
  146. the selected lines.
  147. Documentation comments
  148. ~~~~~~~~~~~~~~~~~~~~~~
  149. Use the following format for documentation comments above uniforms, with **two**
  150. leading asterisks (``/**``) and follow-up asterisks on every line:
  151. .. code-block:: glsl
  152. /**
  153. * This is a documentation comment.
  154. * These lines will appear in the inspector when hovering the shader parameter
  155. * named "Something".
  156. * You can use [b]BBCode[/b] [i]formatting[/i] in the comment.
  157. */
  158. uniform int something = 1;
  159. These comments will appear when hovering a property in the inspector. If you
  160. don't wish the comment to be visible in the inspector, use the standard comment
  161. syntax instead (``// ...`` or ``/* ... */`` with only one leading asterisk).
  162. Whitespace
  163. ~~~~~~~~~~
  164. Always use one space around operators and after commas. Also, avoid extraneous spaces
  165. in function calls.
  166. **Good**:
  167. .. code-block:: glsl
  168. COLOR.r = 5.0;
  169. COLOR.r = COLOR.g + 0.1;
  170. COLOR.b = some_function(1.0, 2.0);
  171. **Bad**:
  172. .. code-block:: glsl
  173. COLOR.r=5.0;
  174. COLOR.r = COLOR.g+0.1;
  175. COLOR.b = some_function (1.0,2.0);
  176. Don't use spaces to align expressions vertically:
  177. .. code-block:: glsl
  178. ALBEDO.r = 1.0;
  179. EMISSION.r = 1.0;
  180. Floating-point numbers
  181. ~~~~~~~~~~~~~~~~~~~~~~
  182. Always specify at least one digit for both the integer and fractional part. This
  183. makes it easier to distinguish floating-point numbers from integers, as well as
  184. distinguishing numbers greater than 1 from those lower than 1.
  185. **Good**:
  186. .. code-block:: glsl
  187. void fragment() {
  188. ALBEDO.rgb = vec3(5.0, 0.1, 0.2);
  189. }
  190. **Bad**:
  191. .. code-block:: glsl
  192. void fragment() {
  193. ALBEDO.rgb = vec3(5., .1, .2);
  194. }
  195. Accessing vector members
  196. ------------------------
  197. Use ``r``, ``g``, ``b``, and ``a`` when accessing a vector's members if it
  198. contains a color. If the vector contains anything else than a color, use ``x``,
  199. ``y``, ``z``, and ``w``. This allows those reading your code to better
  200. understand what the underlying data represents.
  201. **Good**:
  202. .. code-block:: glsl
  203. COLOR.rgb = vec3(5.0, 0.1, 0.2);
  204. **Bad**:
  205. .. code-block:: glsl
  206. COLOR.xyz = vec3(5.0, 0.1, 0.2);
  207. Naming conventions
  208. ------------------
  209. These naming conventions follow the Godot Engine style. Breaking these will make
  210. your code clash with the built-in naming conventions, leading to inconsistent
  211. code.
  212. Functions and variables
  213. ~~~~~~~~~~~~~~~~~~~~~~~
  214. Use snake\_case to name functions and variables:
  215. .. code-block:: glsl
  216. void some_function() {
  217. float some_variable = 0.5;
  218. }
  219. Constants
  220. ~~~~~~~~~
  221. Write constants with CONSTANT\_CASE, that is to say in all caps with an
  222. underscore (\_) to separate words:
  223. .. code-block:: glsl
  224. const float GOLDEN_RATIO = 1.618;
  225. Preprocessor directives
  226. ~~~~~~~~~~~~~~~~~~~~~~~
  227. :ref:`doc_shader_preprocessor` directives should be written in CONSTANT__CASE.
  228. Directives should be written without any indentation before them, even if
  229. nested within a function.
  230. To preserve the natural flow of indentation when shader errors are printed to
  231. the console, extra indentation should **not** be added within ``#if``,
  232. ``#ifdef`` or ``#ifndef`` blocks:
  233. **Good**:
  234. .. code-block:: glsl
  235. #define HEIGHTMAP_ENABLED
  236. void fragment() {
  237. vec2 position = vec2(1.0, 2.0);
  238. #ifdef HEIGHTMAP_ENABLED
  239. sample_heightmap(position);
  240. #endif
  241. }
  242. **Bad**:
  243. .. code-block:: glsl
  244. #define heightmap_enabled
  245. void fragment() {
  246. vec2 position = vec2(1.0, 2.0);
  247. #ifdef heightmap_enabled
  248. sample_heightmap(position);
  249. #endif
  250. }
  251. Code order
  252. ----------
  253. We suggest to organize shader code this way:
  254. .. code-block:: glsl
  255. 01. shader type declaration
  256. 02. render mode declaration
  257. 03. // docstring
  258. 04. uniforms
  259. 05. constants
  260. 06. varyings
  261. 07. other functions
  262. 08. vertex() function
  263. 09. fragment() function
  264. 10. light() function
  265. We optimized the order to make it easy to read the code from top to bottom, to
  266. help developers reading the code for the first time understand how it works, and
  267. to avoid errors linked to the order of variable declarations.
  268. This code order follows two rules of thumb:
  269. 1. Metadata and properties first, followed by methods.
  270. 2. "Public" comes before "private". In a shader language's context, "public"
  271. refers to what's easily adjustable by the user (uniforms).
  272. Local variables
  273. ~~~~~~~~~~~~~~~
  274. Declare local variables as close as possible to their first use. This makes it
  275. easier to follow the code, without having to scroll too much to find where the
  276. variable was declared.