shaders_style_guide.rst 8.9 KB

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