shaders_style_guide.rst 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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/gles3/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. uniform sampler2D screen_texture : hint_screen_texture, repeat_disable, filter_nearest;
  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. Whitespace
  148. ~~~~~~~~~~
  149. Always use one space around operators and after commas. Also, avoid extraneous spaces
  150. in function calls.
  151. **Good**:
  152. .. code-block:: glsl
  153. COLOR.r = 5.0;
  154. COLOR.r = COLOR.g + 0.1;
  155. COLOR.b = some_function(1.0, 2.0);
  156. **Bad**:
  157. .. code-block:: glsl
  158. COLOR.r=5.0;
  159. COLOR.r = COLOR.g+0.1;
  160. COLOR.b = some_function (1.0,2.0);
  161. Don't use spaces to align expressions vertically:
  162. .. code-block:: glsl
  163. ALBEDO.r = 1.0;
  164. EMISSION.r = 1.0;
  165. Floating-point numbers
  166. ~~~~~~~~~~~~~~~~~~~~~~
  167. Always specify at least one digit for both the integer and fractional part. This
  168. makes it easier to distinguish floating-point numbers from integers, as well as
  169. distinguishing numbers greater than 1 from those lower than 1.
  170. **Good**:
  171. .. code-block:: glsl
  172. void fragment() {
  173. ALBEDO.rgb = vec3(5.0, 0.1, 0.2);
  174. }
  175. **Bad**:
  176. .. code-block:: glsl
  177. void fragment() {
  178. ALBEDO.rgb = vec3(5., .1, .2);
  179. }
  180. Accessing vector members
  181. ------------------------
  182. Use ``r``, ``g``, ``b``, and ``a`` when accessing a vector's members if it
  183. contains a color. If the vector contains anything else than a color, use ``x``,
  184. ``y``, ``z``, and ``w``. This allows those reading your code to better
  185. understand what the underlying data represents.
  186. **Good**:
  187. .. code-block:: glsl
  188. COLOR.rgb = vec3(5.0, 0.1, 0.2);
  189. **Bad**:
  190. .. code-block:: glsl
  191. COLOR.xyz = vec3(5.0, 0.1, 0.2);
  192. Naming conventions
  193. ------------------
  194. These naming conventions follow the Godot Engine style. Breaking these will make
  195. your code clash with the built-in naming conventions, leading to inconsistent
  196. code.
  197. Functions and variables
  198. ~~~~~~~~~~~~~~~~~~~~~~~
  199. Use snake\_case to name functions and variables:
  200. .. code-block:: glsl
  201. void some_function() {
  202. float some_variable = 0.5;
  203. }
  204. Constants
  205. ~~~~~~~~~
  206. Write constants with CONSTANT\_CASE, that is to say in all caps with an
  207. underscore (\_) to separate words:
  208. .. code-block:: glsl
  209. const float GOLDEN_RATIO = 1.618;
  210. Preprocessor directives
  211. ~~~~~~~~~~~~~~~~~~~~~~~
  212. :ref:`doc_shader_preprocessor` directives should be written in CONSTANT__CASE.
  213. Directives should be written without any indentation before them, even if
  214. nested within a function.
  215. To preserve the natural flow of indentation when shader errors are printed to
  216. the console, extra indentation should **not** be added within ``#if``,
  217. ``#ifdef`` or ``#ifndef`` blocks:
  218. **Good**:
  219. .. code-block:: glsl
  220. #define HEIGHTMAP_ENABLED
  221. void fragment() {
  222. vec2 position = vec2(1.0, 2.0);
  223. #ifdef HEIGHTMAP_ENABLED
  224. sample_heightmap(position);
  225. #endif
  226. }
  227. **Bad**:
  228. .. code-block:: glsl
  229. #define heightmap_enabled
  230. void fragment() {
  231. vec2 position = vec2(1.0, 2.0);
  232. #ifdef heightmap_enabled
  233. sample_heightmap(position);
  234. #endif
  235. }
  236. Code order
  237. ----------
  238. We suggest to organize shader code this way:
  239. .. code-block:: glsl
  240. 01. shader type declaration
  241. 02. render mode declaration
  242. 03. // docstring
  243. 04. uniforms
  244. 05. constants
  245. 06. varyings
  246. 07. other functions
  247. 08. vertex() function
  248. 09. fragment() function
  249. 10. light() function
  250. We optimized the order to make it easy to read the code from top to bottom, to
  251. help developers reading the code for the first time understand how it works, and
  252. to avoid errors linked to the order of variable declarations.
  253. This code order follows two rules of thumb:
  254. 1. Metadata and properties first, followed by methods.
  255. 2. "Public" comes before "private". In a shader language's context, "public"
  256. refers to what's easily adjustable by the user (uniforms).
  257. Local variables
  258. ~~~~~~~~~~~~~~~
  259. Declare local variables as close as possible to their first use. This makes it
  260. easier to follow the code, without having to scroll too much to find where the
  261. variable was declared.