فهرست منبع

Merge pull request #316 from defold/manual-shader-includes

Added shader include manual entry
Jhonny Göransson 2 سال پیش
والد
کامیت
62285b815f
1فایلهای تغییر یافته به همراه77 افزوده شده و 0 حذف شده
  1. 77 0
      docs/en/manuals/shader.md

+ 77 - 0
docs/en/manuals/shader.md

@@ -93,6 +93,83 @@ Varying variables
 
   ![Varying interpolation](images/shader/varying.png){srcset="images/shader/[email protected] 2x"}
 
+## Including snippets into shaders
+
+Shaders in Defold support including source code from files within the project that have have the `.glsl` extension. To include a glsl file from a shader, use the `#include` pragma either with double quotations or brackets. Includes must have either project relative paths or a path that is relative from the file that is including it:
+
+```glsl
+// In file /main/my-shader.fp
+
+// Absolute path
+#include "/main/my-snippet.glsl"
+// The file is in the same folder
+#include "my-snippet.glsl"
+// The file is in a sub-folder on the same level as 'my-shader'
+#include "sub-folder/my-snippet.glsl"
+// The file is in a sub-folder on the parent directory, i.e /some-other-folder/my-snippet.glsl
+#include "../some-other-folder/my-snippet.glsl"
+// The file is on the parent directory, i.e /root-level-snippet.glsl
+#include "../root-level-snippet.glsl"
+```
+
+::: sidenote
+Shader includes are available starting from version 1.4.2
+:::
+
+There are some caveats to how includes are picked up:
+
+  - Files must be project relative, meaning that you can only include files that are located within the project. Any absolute path must be specified with a leading `/`
+  - You can include code anywhere in the file, but you cannot include a file inline in a statement. E.g `const float #include "my-float-name.glsl" = 1.0` will not work
+
+### Header guards
+
+Snippets can themselves include other `.glsl` files, which means that the final produced shader can potentially include the same code several times, and depending on the contents of the files you can end up with compile issues due to having the same symbols stated more than once. To avoid this, you can use *header guards*, which is a common concept in several programming languages. Example:
+
+```glsl
+// In my-shader.vs
+#include "math-functions.glsl"
+#include "pi.glsl"
+
+// In math-functions.glsl
+#include "pi.glsl"
+
+// In pi.glsl
+const float PI = 3.14159265359;
+```
+
+In this example, the `PI` constant will be defined twice, which will cause compiler errors when running the project. You should instead protect the contents with header guards:
+
+```glsl
+// In pi.glsl
+#ifndef PI_GLSL_H
+#define PI_GLSL_H
+
+const float PI = 3.14159265359;
+
+#endif // PI_GLSL_H
+```
+
+The code from `pi.glsl` will be expanded twice in `my-shader.vs`, but since you have wrapped it in header guards the PI symbol will only be defined once and the shader will compile successfully.
+
+However, this is not always strict necessary depending of use-case. If instead you want to reuse code locally in a function or elsewhere where you don't need the values to be globally available in the shader code, you should probably not use header guards. Example:
+
+```glsl
+// In red-color.glsl
+vec3 my_red_color = vec3(1.0, 0.0, 0.0);
+
+// In my-shader.fp
+vec3 get_red_color()
+{
+  #include "red-color.glsl"
+  return my_red_color;
+}
+
+vec3 get_red_color_inverted()
+{
+  #include "red-color.glsl"
+  return 1.0 - my_red_color;
+}
+```
 
 ## The rendering process