jme3_shadernodes.html 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><title>Shader Nodes</title><link rel="stylesheet" href="./asciidoctor.css">
  2. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  3. <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"><link rel="stylesheet" href="/home/travis/build/jMonkeyEngine/wiki/build/asciidoc/html5/jme3/advanced/twemoji-awesome.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/jme3/advanced/jme3_shadernodes.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/jme3/advanced/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"></div><h1>Shader Nodes</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#motivations">Motivations</a></li><li><a href="#what-is-a-shader-node">What is a Shader Node?</a></li><li><a href="#shader-node-definition">Shader Node definition</a><ul class="sectlevel2"><li><a href="#example">Example</a></li><li><a href="#declare-an-array">Declare an array</a></li></ul></li><li><a href="#shader-node-code">Shader Node code</a></li><li><a href="#shader-node-declaration">Shader Node declaration</a></li><li><a href="#complete-material-definition-and-shader-nodes-example">Complete material definition and Shader Nodes example</a></li></ul></div></div><div id="content"><div class="sect1"><h2 id="motivations">Motivations</h2><div class="sectionbody"><div class="paragraph"><p>jME3 material system is entirely based on shaders. While it&#8217;s pretty powerful, this system has some issues and limitations :</p></div>
  4. <div class="ulist"><ul><li><p>Monolithic shaders have a serious lack of flexibility, and it can be daunting to get into the code for inexperienced users.</p></li><li><p>Maintenance ease of such shaders is poor. (for example the whole lighting shaders represent around 500 lines of code, and it could be a lot worse with more features)</p></li><li><p>Adding new features to those shaders decrease the ease of maintenance a lot. This point made us reluctant to do so and some feature were never added (Fog to name it, but many more).</p></li><li><p>Users can&#8217;t add their own feature to the shader unless they fork it, and fall back to the same issues explained in previous points.</p></li></ul></div>
  5. <div class="paragraph"><p>Shader Nodes were designed with this in mind and are the fruit of many long discussions in the core chat balancing the pros and cons of this or that pattern.<br>
  6. At first this system was referred to as “Shader injection. The basic idea was to allow users to inject code into shaders with a tag replacement system.<br>
  7. We finally came with a different concept called Shader Nodes, that is inspired from blender nodes system for textures and post process.<br>
  8. <strong>The final shader is generated at run time by the system by assembling shader nodes together.</strong></p></div></div></div>
  9. <div class="sect1"><h2 id="what-is-a-shader-node">What is a Shader Node?</h2><div class="sectionbody"><div class="paragraph"><p>Conceptually, it&#8217;s just a self sufficient piece of glsl code that accepts inputs and produce some outputs.<br>
  10. Inputs are glsl variables that may be fed by previous nodes output values.<br>
  11. Outputs are glsl variables fed with values computed in the shader node code.<br></p></div>
  12. <div class="paragraph"><p>In practice it&#8217;s a bit more than that.A shader node is declined in several parts :</p></div>
  13. <div class="ulist"><ul><li><p>A shader node definition, defining :</p><div class="ulist"><ul><li><p>The type of shader node (Vertex or Fragment for now)</p></li><li><p>The minimal glsl version needed for the shader node</p></li><li><p>The path to the shader file (containing the shader code heh)</p></li><li><p><strong>A mandatory documentation block</strong> for this Shader node. As I hope many users will do their own nodes and contribute them back this point is crucial.</p></li><li><p>A list of inputs accepted by this shader (typed glsl variable optional or needed for the code to run properly)</p></li><li><p>A list of outputs produced by this shader (typed glsl variable computed and fed by the node&#8217;s code)</p></li></ul></div></li><li><p>The actual shader code file (.vert or .frag depending on the node&#8217;s type like any shader file)</p></li><li><p>A shader node declaration having :</p><div class="ulist"><ul><li><p>A unique name(in the shader scope)</p></li><li><p>The shader node definition it&#8217;s based on</p></li><li><p>An optional activation condition (based on the actual define system)</p></li><li><p>A list of input mapping (what will be actually fed to those inputs)</p></li><li><p>A list of output mapping (what will be output to the global output of the shader)</p></li></ul></div></li></ul></div></div></div>
  14. <div class="sect2"><h3 id="shader-node-definition">Shader Node definition</h3><div class="paragraph"><p>First ShaderNodes have to be defined either in a separate file (j3sn for jme3 shader node) or directly embed in the Technique block of the j3md file.<br>
  15. Please refer to this documentation for global structure of a j3md file
  16. <a href="../../jme3/advanced/material_specification.html">jMonkeyEngine3 Material Specification</a></p></div>
  17. <div class="paragraph"><p>All is included in a <strong>ShaderNodeDefinitions</strong> bloc. This block can have several nodes defined (it&#8217;s recommended to define nodes that have strong dependencies with each other in the same j3sn file).<br>
  18. A ShaderNode is declared in a <strong>ShaderNodeDefinition</strong> block.<br>
  19. The global structure should look like this :</p></div>
  20. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">ShaderNodeDefinitions{
  21. ShaderNodeDefinition &lt;NodeDefName&gt;{
  22. <span class="predefined-type">Type</span> : &lt;ShaderType&gt;
  23. Shader &lt;ShaderLangAndVersion&gt; : &lt;ShaderPath&gt;
  24. [Shader &lt;ShaderLangAndVersion&gt; : &lt;ShaderPath&gt;]
  25. [...]
  26. Documentation {
  27. &lt;DocContent&gt;
  28. }
  29. Input {
  30. &lt;GlslVarType&gt; &lt;VarName&gt;
  31. [&lt;GlslVarType&gt; &lt;VarName&gt;]
  32. [...]
  33. }
  34. Output {
  35. &lt;GlslVarType&gt; &lt;VarName&gt;
  36. [&lt;GlslVarType&gt; &lt;VarName&gt;]
  37. [...]
  38. }
  39. }
  40. [ShaderNodeDefinition &lt;NodeDef2Name&gt; {
  41. [...]
  42. }]
  43. [...]
  44. }</code></pre></div></div>
  45. <div class="paragraph"><p>All that is not between [] is mandatory.</p></div>
  46. <div class="ulist"><ul><li><p><u>ShaderNodeDefinition</u> : the definition block. You can have several definition in the same ShaderNodeDefinitions block.</p><div class="ulist"><ul><li><p><strong>NodeDefName</strong> : The name of this ShaderNodeDefinition</p></li></ul></div></li><li><p><u>Type</u> : define the type of this shader node</p><div class="ulist"><ul><li><p><strong>ShaderType</strong> : The type of shader for this definition. For now only “Vertex and “Fragment are supported.</p></li></ul></div></li><li><p><u>Shader</u> : the version and path of the shader code to use. note that you can have several shader with different GLSL version. The generator will pick the relevant one according to GPU capabilities.</p><div class="ulist"><ul><li><p><strong>ShaderLangAndVersion</strong> : follows the same syntax than the shader declaration in the j3md file : GLSL&lt;version&gt;, version being 100 for glsl 1.0 , 130 for glsl 1.3, 150 for glsl 1.5 and so on. Note that this is the <strong>minimum</strong> glsl version this shader supports</p></li><li><p><strong>ShaderPath</strong> the path to the shader code file (relative to the asset folder)</p></li></ul></div></li><li><p><u>Documentation</u> : the documentation block. This is mandatory and I really recommend filling this if you want to contribute your shader nodes. This documentation will be read buy the SDK and presented to users willing to add this node to their material definitions. This should contain a brief description of the node and a description for each input and ouput.</p><div class="ulist"><ul><li><p><strong>@input</strong> can be use to prefix an input name so the sdk recognize it and format it accordingly. the syntax id @input &lt;inputName&gt; &lt;description&gt;.</p></li><li><p><strong>@output</strong> can be use to prefix an output name so the sdk recognize it and format it accordingly. the syntax id @output &lt;inputName&gt; &lt;description&gt;</p></li></ul></div></li><li><p><u>Input</u> : The input block containing all the inputs of this node. A node can have 1 or several inputs.</p><div class="ulist"><ul><li><p><strong>GlslVarType</strong> : a valid glsl variable type that will be used in the shader for this input. see <a href="http://www.opengl.org/wiki/GLSL_Type">http://www.opengl.org/wiki/GLSL_Type</a> and the “Declare an array chapter</p></li><li><p><strong>VarName</strong> : the name of the variable. Note that you can&#8217;t have several inputs with the same name.</p></li></ul></div></li><li><p><u>Output</u> : The output block containing all the outputs of this node. A node can have 1 or several outputs.</p><div class="ulist"><ul><li><p><strong>GlslVarType</strong> : a valid glsl variable type that will be used in the shader for this input. see <a href="http://www.opengl.org/wiki/GLSL_Type">http://www.opengl.org/wiki/GLSL_Type</a> and the “Declare an array chapter</p></li><li><p><strong>VarName</strong> : the name of the variable. Note that you can&#8217;t have several outputs with the same name.</p></li></ul></div></li></ul></div>
  47. <div class="admonitionblock note"><table><tr><td class="icon"><i class="fa icon-note" title="Note"></i></td><td class="content"><div class="paragraph"><p>If you use the same name for an input and an ouput, the generator will consider them as the SAME variable so they should be of the same glsl type.</p></div></td></tr></table></div>
  48. <div class="sect2"><h3 id="example">Example</h3><div class="paragraph"><p>Here is a typical shader node definition.</p></div>
  49. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">ShaderNodeDefinitions{
  50. ShaderNodeDefinition LightMapping{
  51. <span class="predefined-type">Type</span>: Fragment
  52. Shader GLSL100: Common/MatDefs/ShaderNodes/LightMapping/lightMap.frag
  53. Documentation {
  54. This Node is responsible <span class="keyword">for</span> multiplying a light mapping contribution to a given color.
  55. <span class="annotation">@input</span> texCoord the texture coordinates to use <span class="keyword">for</span> light mapping
  56. <span class="annotation">@input</span> lightMap the texture to use <span class="keyword">for</span> light mapping
  57. <span class="annotation">@input</span> color the color the lightmap color will be multiplied to
  58. <span class="annotation">@output</span> color the resulting color
  59. }
  60. Input{
  61. vec2 texCoord
  62. sampler2D lightMap
  63. vec4 color
  64. }
  65. Output{
  66. vec4 color
  67. }
  68. }
  69. }</code></pre></div></div></div>
  70. <div class="sect2"><h3 id="declare-an-array">Declare an array</h3><div class="paragraph"><p>To declare an array you have to specify its size between square brackets.<br>
  71. <strong>Constant size</strong><br>
  72. The size can be an int constant.<br>
  73. <em>Example</em></p></div>
  74. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code> float myArray[10]</code></pre></div></div>
  75. <div class="paragraph"><p>This will declare a float array with 10 elements.
  76. Any material parameter mapped with this array should be of FloatArray type and it&#8217;s size will be assumed as 10 when the shader is generated.</p></div>
  77. <div class="paragraph"><p><strong>Material parameter driven size</strong><br>
  78. The size can be dynamic and driven by a material parameter. GLSL does not support non constant values for array declaration so this material parameter will be mapped to a define.<br>
  79. <em>Example</em></p></div>
  80. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code> float myArray[NumberOfElements]</code></pre></div></div>
  81. <div class="paragraph"><p>This declares a float array with the size depending on the value of the NumberOfElement material parameter.<br>
  82. NumberOfElement <strong>HAS</strong> to be declared in the material definition as a material parameter. It will be mapped to a define and used in the shader.</p></div>
  83. <div class="admonitionblock note"><table><tr><td class="icon"><i class="fa icon-note" title="Note"></i></td><td class="content"><div class="paragraph"><p>If this value change the shader will have to be recompiled, due to the fact that it&#8217;s mapped to a define.</p></div></td></tr></table></div></div></div>
  84. <div class="sect1"><h2 id="shader-node-code">Shader Node code</h2><div class="sectionbody"><div class="paragraph"><p>The shader code associated with a Shader node is similar to any shader code.<br>
  85. The code for a Vertex shader node should be in a .vert file and the code for a Fragment shader node should be in a .frag file.
  86. It has a declarative part containing variable declaration, function declaration and so on… And a main part that is embed in a “void main(){} block.<br>
  87. Input and output variables declared in the shader node definition can be used <strong>without</strong> being declared in the shader code. ( they shouldn&#8217;t even or you&#8217;ll have issues).<br>
  88. Here is a the code of the LightMap.frag shader.</p></div>
  89. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="type">void</span> main(){
  90. color *= texture2D(lightMap, texCoord);
  91. }</code></pre></div></div>
  92. <div class="paragraph"><p>Very simple, it&#8217;s just a texture fetch, but of course anything can be done.<br>
  93. <strong>Do not declare uniforms, attributes or varyings in a shader node code</strong>, the Generator will handle this, just use the inputs and outputs and optional local variables you may need.</p></div></div></div>
  94. <div class="sect1"><h2 id="shader-node-declaration">Shader Node declaration</h2><div class="sectionbody"><div class="paragraph"><p>To create a shader we need to plug shader nodes to each other, but also interact with built in glsl inputs and outputs.
  95. Shader nodes are declared inside the Technique block. The vertex nodes are declared in the VertexShaderNodes block and the fragment nodes are declared in the FragmentShaderNodes block.<br>
  96. Note that if the j3md has ember shader nodes definition (in a ShaderNodesDefinitions block) it <strong>must</strong> be declared before the VertexShaderNodes and FragmentShaderNodes blocks.
  97. Of course there can be several ShaderNode declaration in those block.<br>
  98. Here is how a ShaderNode declaration should look :</p></div>
  99. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">ShaderNode &lt;ShaderNodeName&gt;{
  100. Definition : &lt;DefinitionName&gt; [: &lt;DefinitionPath&gt;]
  101. [<span class="predefined-type">Condition</span> : &lt;ActivationCondition&gt;]
  102. InputMapping{
  103. &lt;InputVariableName&gt;[.&lt;Swizzle&gt;] = &lt;NameSpace&gt;.&lt;VarName&gt;[.&lt;Swizzle&gt;] [: &lt;MappingCondition&gt;]
  104. [...]
  105. }
  106. [OutputMapping{
  107. &lt;NameSpace&gt;.&lt;VarName&gt;[.&lt;Swizzle&gt;] = &lt;OutputVariableName&gt;[.&lt;Swizzle&gt;] [: &lt;MappingCondition&gt;]
  108. [...]
  109. }]
  110. }</code></pre></div></div>
  111. <div class="ulist"><ul><li><p><u>ShaderNode</u> the shader node block</p><div class="ulist"><ul><li><p><strong>ShaderNodeName</strong> the name of this shader node, can be anything, but has to be <strong>unique</strong> in the shader scope.</p></li></ul></div></li><li><p><u>Definition</u> : a reference to the shader node definition.</p><div class="ulist"><ul><li><p><strong>DefinitionName</strong> : the name of the definition this Node use. this definition can be declared in the same j3md or in its own j3sn file.</p></li><li><p><strong>DefinitionPath</strong> : in case the definition is declared in it&#8217;s own j3sn file, you have to set the path to this file here.</p></li></ul></div></li><li><p><u>Condition</u> a condition that dictates if the node is active or not.</p><div class="ulist"><ul><li><p><strong>ActivationCondition</strong> : The condition for this node to be used. Today we use Defines to use different blocks of code used depending on the state of a Material Parameter. The condition here use the exact same paradigm. A valid condition must be the name of a material parameter or any combinations using logical operators &#8220;||,“&amp;&amp;,“! or grouping characters “( and “). The generator will create the corresponding define and the shader node code will be embed into and #ifdef statement.</p></li></ul></div></li></ul></div>
  112. <div class="paragraph"><p>For example, let&#8217;s say we have a Color and ColorMap material parameter, this condition “Color || ColorMap will generate this statement :</p></div>
  113. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"> <span class="error">#</span><span class="keyword">if</span> defined(COLOR) || defined(COLORMAP)
  114. ...
  115. <span class="error">#</span>endif</code></pre></div></div>
  116. <div class="ulist"><ul><li><p><u>InputMapping</u> the wiring of the inputs of this node, coming from previous node&#8217;s outputs or from built in glsl inputs.</p><div class="ulist"><ul><li><p><strong>InputVariableName</strong> : the name of the variable to map as declared in the definition.</p></li><li><p><strong>Swizzle</strong> : Swizling for the preceding variable. More information on glsl swizzling on this page <a href="http://www.opengl.org/wiki/GLSL_Type">http://www.opengl.org/wiki/GLSL_Type</a>.</p></li><li><p><strong>NameSpace</strong> : The generator will use variable name space to avoid collision between variable names. Name space can be one of these values :</p><div class="ulist"><ul><li><p><strong>MatParam</strong> : the following variable is a Material Parameter declared in the MaterialParameters block of the materialDefinition.</p></li><li><p><strong>WorldParam</strong> : the following variable is a World Parameter declared in the WorldParameters block of the current technique block. World parameters can be one of those declared in this file : <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/shader/UniformBinding.java">https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/shader/UniformBinding.java</a></p></li><li><p><strong>Attr</strong> : the following variable is a shader attribute. It can be one those declared in the Type enum of the VertexBuffer class <a href="https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java">https://github.com/jMonkeyEngine/jmonkeyengine/blob/master/jme3-core/src/main/java/com/jme3/scene/VertexBuffer.java</a>.</p></li><li><p><strong>Global</strong> : the variable is a global variable to the shader. Global variables will be assign at the end of the shader to glsl built in outputs : gl_Position for the vertex shader, or to one of the possible outputs of the fragment shader (for example gl_FragColor). The global variable can have what ever name pleases you, it will assigned in the order they&#8217;ve been found in the declaration to the shader output. <strong>Global variables can be inputs of a shader node. Global variables are forced to be vec4 and are defaulted to the value of the attribute inPosition in the vertex shader and vec4(1.0)(opaque white color) in the fragment shader</strong>.</p></li><li><p><strong>The name of a previous shader node</strong> : this must be followed by and output variable of a the named shader node. This is what allows one to plug outputs from a node to inputs of another.</p></li></ul></div></li><li><p><strong>VarName</strong> : the name of the variable to assign to the input. This variable must be known in name space declared before.</p></li><li><p><strong>MappingCondition</strong> : Follows the same rules as the activation condition for the shaderNode, this mapping will be embed in a #ifdef statement n the resulting shader.</p></li></ul></div></li><li><p><u>OutputMapping</u> : This block is optional, as mapping of output will be done in input mapping block of following shaderNodes, ecept if you want to output a value to the Global output of the shader.</p><div class="ulist"><ul><li><p><strong>NameSpace</strong> : the name space of the output to assign, this can only be “Global here.</p></li><li><p><strong>VarName</strong> : the name of a global output (can be anything, just be aware that 2 different names result in 2 different outputs).</p></li><li><p><strong>OutputVariable</strong> : Must be an output of the current node&#8217;s definition.</p></li><li><p><strong>MappingCondition</strong> : Same as before.</p></li></ul></div></li></ul></div></div></div>
  117. <div class="sect1"><h2 id="complete-material-definition-and-shader-nodes-example">Complete material definition and Shader Nodes example</h2><div class="sectionbody"><div class="paragraph"><p>Here is an example of a very simple Material definition that just displays a solid color (controlled by a material parameter) on a mesh.</p></div>
  118. <div class="admonitionblock important"><table><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content"><div class="paragraph"><p>Shader Nodes only work if there is no shader declared in the technique. If you want to bypass the Shader Nodes, you can put a VertexShader and a FragmentShader statement in the technique and the shader nodes will be ignored.</p></div></td></tr></table></div>
  119. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">MaterialDef Simple {
  120. MaterialParameters {
  121. <span class="predefined-type">Color</span> <span class="predefined-type">Color</span>
  122. }
  123. Technique {
  124. WorldParameters {
  125. WorldViewProjectionMatrix
  126. }
  127. VertexShaderNodes {
  128. ShaderNode CommonVert {
  129. Definition : CommonVert : Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn
  130. InputMappings {
  131. worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
  132. modelPosition = Global.position.xyz
  133. }
  134. OutputMappings {
  135. Global.position = projPosition
  136. }
  137. }
  138. }
  139. FragmentShaderNodes {
  140. ShaderNode ColorMult {
  141. Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn
  142. InputMappings {
  143. color1 = MatParam.Color
  144. color2 = Global.color
  145. }
  146. OutputMappings {
  147. Global.color = outColor
  148. }
  149. }
  150. }
  151. }
  152. }</code></pre></div></div>
  153. <div class="paragraph"><p>This Material definition has one Default technique with 2 node declarations.<br>
  154. <strong><u>CommonVert Definition</u></strong><br>
  155. CommonVert is a vertex shader node that has commonly used input and outputs of a vertex shader. It also computes the position of the vertex in projection space.<br>
  156. Here is the definition content (Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn) :</p></div>
  157. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">ShaderNodesDefinitions {
  158. ShaderNodeDefinition CommonVert {
  159. <span class="predefined-type">Type</span>: Vertex
  160. Shader GLSL100: Common/MatDefs/ShaderNodes/Common/commonVert.vert
  161. Documentation {
  162. This Node is responsible <span class="keyword">for</span> computing vertex position in projection space.
  163. It also can pass texture coordinates <span class="integer">1</span> &amp; <span class="integer">2</span>, and vertexColor to the frgment shader as varying (or inputs <span class="keyword">for</span> glsl &gt;=<span class="float">1.3</span>)
  164. <span class="annotation">@input</span> modelPosition the vertex position in model space (usually assigned with Attr.inPosition or Global.position)
  165. <span class="annotation">@input</span> worldViewProjectionMatrix the World <span class="predefined-type">View</span> Projection Matrix transforms model space to projection space.
  166. <span class="annotation">@input</span> texCoord1 The first texture coordinates of the vertex (usually assigned with Attr.inTexCoord)
  167. <span class="annotation">@input</span> texCoord2 The second texture coordinates of the vertex (usually assigned with Attr.inTexCoord2)
  168. <span class="annotation">@input</span> vertColor The color of the vertex (usually assigned with Attr.inColor)
  169. <span class="annotation">@output</span> projPosition <span class="predefined-type">Position</span> of the vertex in projection space.(usually assigned to Global.position)
  170. <span class="annotation">@output</span> vec2 texCoord1 The first texture coordinates of the vertex (output as a varying)
  171. <span class="annotation">@output</span> vec2 texCoord2 The second texture coordinates of the vertex (output as a varying)
  172. <span class="annotation">@output</span> vec4 vertColor The color of the vertex (output as a varying)
  173. }
  174. Input{
  175. vec3 modelPosition
  176. mat4 worldViewProjectionMatrix
  177. vec2 texCoord1
  178. vec2 texCoord2
  179. vec4 vertColor
  180. }
  181. Output{
  182. vec4 projPosition
  183. vec2 texCoord1
  184. vec2 texCoord2
  185. vec4 vertColor
  186. }
  187. }
  188. }</code></pre></div></div>
  189. <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>Note that texCoord1/2 and vertColor are declared both as input and output. The generator will use the same variables for them.</p></div></td></tr></table></div>
  190. <div class="paragraph"><p>Here is the shader Node code ( Common/MatDefs/ShaderNodes/Common/commonVert.vert).</p></div>
  191. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="type">void</span> main(){
  192. projPosition = worldViewProjectionMatrix * vec4(modelPosition, <span class="float">1.0</span>);
  193. }</code></pre></div></div>
  194. <div class="paragraph"><p>As you can see all the inputs and outputs are not used. That&#8217;s because most of them are attributes meant to be passed to the fragment shader as varyings. All the wiring will be handled by the generator only if those variables are used in an input or output mapping.</p></div>
  195. <div class="paragraph"><p><strong><u>CommonVert input mapping</u></strong><br>
  196. Here we have the most basic yet mandatory thing in a vertex shader, computing vertex position in projection space. For this we have 2 mappings :</p></div>
  197. <div class="ulist"><ul><li><p><strong>worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix</strong> : the input parameter worldViewProjectionMatrix is assigned with the WorldViewProjectionMatrix World parameter declared in the WorlParameters block of the technique.</p></li><li><p><strong>modelPosition = Global.position.xyz</strong> : the modelPosition (understand the vertex position in the model coordinate space) is assigned with the Global position variable.</p></li></ul></div>
  198. <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>As mentioned before Global position is initialized with the attribute inPosition, so this is equivalent to :</p></div>
  199. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">modelPosition = Attr.inPosition.xyz</code></pre></div></div></td></tr></table></div>
  200. <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>Also note the swizzle of the Global.position variable. ModelPosition is a vec3 and GlobalPosition is a vec4 so we just take the first 3 components.</p></div></td></tr></table></div>
  201. <div class="paragraph"><p><strong><u>CommonVert output mapping</u></strong><br></p></div>
  202. <div class="ulist"><ul><li><p><strong>Global.position = projPosition</strong> : The result of the multiplication of the worldViewProjectionMatrix and the modelPosition is assigned to the Globale position.</p></li></ul></div>
  203. <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>The Global.position variable will be assigned to the gl_Position glsl built in output at the end of the shader.</p></div></td></tr></table></div>
  204. <div class="paragraph"><p><strong><u>ColorMult Definition</u></strong><br>
  205. ColorMult is a very basic Shader Node that takes two colors as input and multiply them.
  206. Here is the definition content (Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn) :</p></div>
  207. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">ShaderNodeDefinitions{
  208. ShaderNodeDefinition ColorMult {
  209. <span class="predefined-type">Type</span>: Fragment
  210. Shader GLSL100: Common/MatDefs/ShaderNodes/Basic/colorMult.frag
  211. Documentation{
  212. Multiplies two colors
  213. <span class="annotation">@input</span> color1 the first color
  214. <span class="annotation">@input</span> color2 the second color
  215. <span class="annotation">@output</span> outColor the resulting color
  216. }
  217. Input {
  218. vec4 color1
  219. vec4 color2
  220. }
  221. Output {
  222. vec4 outColor
  223. }
  224. }
  225. }</code></pre></div></div>
  226. <div class="paragraph"><p>Here is the shader Node code (Common/MatDefs/ShaderNodes/Basic/colorMult.frag).</p></div>
  227. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="type">void</span> main(){
  228. outColor = color1 * color2;
  229. }</code></pre></div></div>
  230. <div class="paragraph"><p><strong><u>ColorMult input mapping</u></strong><br>
  231. All inputs are mapped here :</p></div>
  232. <div class="ulist"><ul><li><p><strong>color1 = MatParam.Color</strong> : The first color is assigned to the Color Material parameter declared in the MaterialParameter block of the material definition.</p></li><li><p><strong>color2 = Global.color</strong> : The second color is assigned with the Global color variable. this is defaulted to vec4(1.0) (opaque white).</p></li></ul></div>
  233. <div class="admonitionblock note"><table><tr><td class="icon"><i class="fa icon-note" title="Note"></i></td><td class="content"><div class="paragraph"><p>In a very complex material def this variable could already have been assigned with a previous Shader Node output.</p></div></td></tr></table></div>
  234. <div class="paragraph"><p><strong><u>ColorMult output mapping</u></strong><br></p></div>
  235. <div class="ulist"><ul><li><p><strong>Global.color = outColor</strong> : the resulting color is assigned to the Global color variable.</p></li></ul></div>
  236. <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>Note that the Global.color variable will be assigned to gl_FragColor (glsl &lt; 1.5) or declared as a Global ouput of the shader (glsl &gt;= 1.5).</p></div></td></tr></table></div>
  237. <div class="admonitionblock tip"><table><tr><td class="icon"><i class="fa icon-tip" title="Tip"></i></td><td class="content"><div class="paragraph"><p>Also note that in case several Global variables are declared, the generator will assign them gl_FragData[i](glsl &lt; 1.5) i being the order the variable has been found in the material def. For glsl &gt;= 1.5 the veriable will just all be declared as shader output in the order they&#8217;ve been found in the declaration.</p></div></td></tr></table></div>
  238. <div class="paragraph"><p><strong><u>Generated shader code</u></strong></p></div>
  239. <div class="admonitionblock important"><table><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content"><div class="paragraph"><p>Don&#8217;t take this code as carved in stone, the generated code can change as optimization of the shader generator goes on.</p></div></td></tr></table></div>
  240. <div class="paragraph"><p>Vertex Shader (glsl 1.0)</p></div>
  241. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">uniform mat4 g_WorldViewProjectionMatrix;
  242. attribute vec4 inPosition;
  243. <span class="type">void</span> main(){
  244. vec4 Global_position = inPosition;
  245. <span class="comment">//CommonVert : Begin</span>
  246. vec3 CommonVert_modelPosition = Global_position.xyz;
  247. vec4 CommonVert_projPosition;
  248. vec2 CommonVert_texCoord1;
  249. vec2 CommonVert_texCoord2;
  250. vec4 CommonVert_vertColor;
  251. CommonVert_projPosition = g_WorldViewProjectionMatrix * vec4(CommonVert_modelPosition, <span class="float">1.0</span>);
  252. Global_position = CommonVert_projPosition;
  253. <span class="comment">//CommonVert : End</span>
  254. gl_Position = Global_position;
  255. }</code></pre></div></div>
  256. <div class="paragraph"><p>All materials parameter, world parameters, attributes varying are declared first. then for each shader node, the declarative part is appended.<br>
  257. For the main function, for each shader node, the input mappings are declared and assigned, the output are declared.<br>
  258. Then the variable names are replaced in the sahder node code with there complete name (NameSpace_varName), material parameters are replaced in the shader code as is.<br>
  259. Then, the output are mapped.</p></div>
  260. <div class="paragraph"><p>As you can see texCoord1/2 and vertColor are declared but never used. That&#8217;s because the generator is not aware of that. By default it will declare all inputs in case they are used in the shaderNode code.
  261. Note that most glsl compiler will optimize this when compiling the shader on the GPU.</p></div>
  262. <div class="paragraph"><p>Fragment Shader (glsl 1.0)</p></div>
  263. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">uniform vec4 m_Color;
  264. <span class="type">void</span> main(){
  265. vec4 Global_color = vec4(<span class="float">1.0</span>);
  266. <span class="comment">//ColorMult : Begin</span>
  267. vec4 ColorMult_color2 = Global_color;
  268. vec4 ColorMult_outColor;
  269. ColorMult_outColor = m_Color * ColorMult_color2;
  270. Global_color = ColorMult_outColor;
  271. <span class="comment">//ColorMult : End</span>
  272. gl_FragColor = Global_color;
  273. }</code></pre></div></div>
  274. <div class="paragraph"><p>Same as for the Vertex shader. Note that the color1 is not declared, because it&#8217;s directly replaced by the material parameter.</p></div>
  275. <div class="admonitionblock important"><table><tr><td class="icon"><i class="fa icon-important" title="Important"></i></td><td class="content"><div class="paragraph"><p>As a rule of thumb you should not assign a value to an input. Inputs are likely to be material paramters or outputs from other shaders and modifying them may cause unexpected behavior, even failure in your resulting shader.</p></div></td></tr></table></div>
  276. <div class="paragraph"><p>For more explanations and design decisions please refer to the <abbr title="specification">spec</abbr> here
  277. <a href="https://docs.google.com/document/d/1S6xO3d1TBz0xcKe_MPTqY9V-QI59AKdg1OGy3U-HeVY/edit?usp=sharing">https://docs.google.com/document/d/1S6xO3d1TBz0xcKe_MPTqY9V-QI59AKdg1OGy3U-HeVY/edit?usp=sharing</a>.</p></div>
  278. <div class="paragraph"><p>Thank you for the brave ones that came through all this reading. I&#8217;m not gonna offer you a prize in exchange of a password, because we ran out of JME thongs…</p></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2019-12-20 23:30:51 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
  279. apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
  280. indexName: 'jmonkeyengine',
  281. inputSelector: '#doc-search',
  282. debug: false // Set debug to true if you want to inspect the dropdown
  283. });</script></body></html>