jme3_shadernodes.adoc 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. = Shader Nodes
  2. :author:
  3. :revnumber:
  4. :revdate: 2016/03/17 20:48
  5. :relfileprefix: ../../
  6. :imagesdir: ../..
  7. ifdef::env-github,env-browser[:outfilesuffix: .adoc]
  8. == Motivations
  9. jME3 material system is entirely based on shaders. While it's pretty powerful, this system has some issues and limitations :
  10. * Monolithic shaders have a serious lack of flexibility, and it can be daunting to get into the code for inexperienced users.
  11. * 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)
  12. * 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).
  13. * Users can't add their own feature to the shader unless they fork it, and fall back to the same issues explained in previous points.
  14. 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. +
  15. 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. +
  16. We finally came with a different concept called Shader Nodes, that is inspired from blender nodes system for textures and post process. +
  17. *The final shader is generated at run time by the system by assembling shader nodes together.*
  18. == What is a Shader Node?
  19. Conceptually, it's just a self sufficient piece of glsl code that accepts inputs and produce some outputs. +
  20. Inputs are glsl variables that may be fed by previous nodes output values. +
  21. Outputs are glsl variables fed with values computed in the shader node code. +
  22. In practice it's a bit more than that.A shader node is declined in several parts :
  23. * A shader node definition, defining :
  24. ** The type of shader node (Vertex or Fragment for now)
  25. ** The minimal glsl version needed for the shader node
  26. ** The path to the shader file (containing the shader code heh)
  27. ** *A mandatory documentation block* for this Shader node. As I hope many users will do their own nodes and contribute them back this point is crucial.
  28. ** A list of inputs accepted by this shader (typed glsl variable optional or needed for the code to run properly)
  29. ** A list of outputs produced by this shader (typed glsl variable computed and fed by the node's code)
  30. * The actual shader code file (.vert or .frag depending on the node's type like any shader file)
  31. * A shader node declaration having :
  32. ** A unique name(in the shader scope)
  33. ** The shader node definition it's based on
  34. ** An optional activation condition (based on the actual define system)
  35. ** A list of input mapping (what will be actually fed to those inputs)
  36. ** A list of output mapping (what will be output to the global output of the shader)
  37. == Shader Node definition
  38. 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. +
  39. Please refer to this documentation for global structure of a j3md file
  40. <<jme3/advanced/material_specification#,jMonkeyEngine3 Material Specification>>
  41. All is included in a *ShaderNodeDefinitions* bloc. This block can have several nodes defined (it's recommended to define nodes that have strong dependencies with each other in the same j3sn file). +
  42. A ShaderNode is declared in a *ShaderNodeDefinition* block. +
  43. The global structure should look like this :
  44. [source,java]
  45. ----
  46. ShaderNodeDefinitions{
  47. ShaderNodeDefinition <NodeDefName>{
  48. Type : <ShaderType>
  49. Shader <ShaderLangAndVersion> : <ShaderPath>
  50. [Shader <ShaderLangAndVersion> : <ShaderPath>]
  51. [...]
  52. Documentation {
  53. <DocContent>
  54. }
  55. Input {
  56. <GlslVarType> <VarName>
  57. [<GlslVarType> <VarName>]
  58. [...]
  59. }
  60. Output {
  61. <GlslVarType> <VarName>
  62. [<GlslVarType> <VarName>]
  63. [...]
  64. }
  65. }
  66. [ShaderNodeDefinition <NodeDef2Name> {
  67. [...]
  68. }]
  69. [...]
  70. }
  71. ----
  72. All that is not between [] is mandatory.
  73. * +++<u>ShaderNodeDefinition</u>+++ : the definition block. You can have several definition in the same ShaderNodeDefinitions block.
  74. ** *NodeDefName* : The name of this ShaderNodeDefinition
  75. * +++<u>Type</u>+++ : define the type of this shader node
  76. ** *ShaderType* : The type of shader for this definition. For now only “Vertex and “Fragment are supported.
  77. * +++<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.
  78. ** *ShaderLangAndVersion* : 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 *minimum* glsl version this shader supports
  79. ** *ShaderPath* the path to the shader code file (relative to the asset folder)
  80. * +++<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.
  81. ** *@input* 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;.
  82. ** *@output* 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;
  83. * +++<u>Input</u>+++ : The input block containing all the inputs of this node. A node can have 1 or several inputs.
  84. ** *GlslVarType* : a valid glsl variable type that will be used in the shader for this input. see link:https://www.khronos.org/opengl/wiki/GLSL_Type[https://www.khronos.org/opengl/wiki/GLSL_Type] and the “Declare an array chapter
  85. ** *VarName* : the name of the variable. Note that you can't have several inputs with the same name.
  86. * +++<u>Output</u>+++ : The output block containing all the outputs of this node. A node can have 1 or several outputs.
  87. ** *GlslVarType* : a valid glsl variable type that will be used in the shader for this input. see link:https://www.khronos.org/opengl/wiki/GLSL_Type[https://www.khronos.org/opengl/wiki/GLSL_Type] and the “Declare an array chapter
  88. ** *VarName* : the name of the variable. Note that you can't have several outputs with the same name.
  89. [NOTE]
  90. ====
  91. 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.
  92. ====
  93. === Example
  94. Here is a typical shader node definition.
  95. [source,java]
  96. ----
  97. ShaderNodeDefinitions{
  98. ShaderNodeDefinition LightMapping{
  99. Type: Fragment
  100. Shader GLSL100: Common/MatDefs/ShaderNodes/LightMapping/lightMap.frag
  101. Documentation {
  102. This Node is responsible for multiplying a light mapping contribution to a given color.
  103. @input texCoord the texture coordinates to use for light mapping
  104. @input lightMap the texture to use for light mapping
  105. @input color the color the lightmap color will be multiplied to
  106. @output color the resulting color
  107. }
  108. Input{
  109. vec2 texCoord
  110. sampler2D lightMap
  111. vec4 color
  112. }
  113. Output{
  114. vec4 color
  115. }
  116. }
  117. }
  118. ----
  119. === Declare an array
  120. To declare an array you have to specify its size between square brackets. +
  121. *Constant size* +
  122. The size can be an int constant. +
  123. _Example_
  124. [source]
  125. ----
  126. float myArray[10]
  127. ----
  128. This will declare a float array with 10 elements.
  129. Any material parameter mapped with this array should be of FloatArray type and it's size will be assumed as 10 when the shader is generated.
  130. *Material parameter driven size* +
  131. 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. +
  132. _Example_
  133. [source]
  134. ----
  135. float myArray[NumberOfElements]
  136. ----
  137. This declares a float array with the size depending on the value of the NumberOfElement material parameter. +
  138. NumberOfElement *HAS* to be declared in the material definition as a material parameter. It will be mapped to a define and used in the shader.
  139. [NOTE]
  140. ====
  141. If this value change the shader will have to be recompiled, due to the fact that it's mapped to a define.
  142. ====
  143. == Shader Node code
  144. The shader code associated with a Shader node is similar to any shader code. +
  145. 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.
  146. 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. +
  147. Input and output variables declared in the shader node definition can be used *without* being declared in the shader code. ( they shouldn't even or you'll have issues). +
  148. Here is a the code of the LightMap.frag shader.
  149. [source,java]
  150. ----
  151. void main(){
  152. color *= texture2D(lightMap, texCoord);
  153. }
  154. ----
  155. Very simple, it's just a texture fetch, but of course anything can be done. +
  156. *Do not declare uniforms, attributes or varyings in a shader node code*, the Generator will handle this, just use the inputs and outputs and optional local variables you may need.
  157. == Shader Node declaration
  158. To create a shader we need to plug shader nodes to each other, but also interact with built in glsl inputs and outputs.
  159. 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. +
  160. Note that if the j3md has ember shader nodes definition (in a ShaderNodesDefinitions block) it *must* be declared before the VertexShaderNodes and FragmentShaderNodes blocks.
  161. Of course there can be several ShaderNode declaration in those block. +
  162. Here is how a ShaderNode declaration should look :
  163. [source,java]
  164. ----
  165. ShaderNode <ShaderNodeName>{
  166. Definition : <DefinitionName> [: <DefinitionPath>]
  167. [Condition : <ActivationCondition>]
  168. InputMapping{
  169. <InputVariableName>[.<Swizzle>] = <NameSpace>.<VarName>[.<Swizzle>] [: <MappingCondition>]
  170. [...]
  171. }
  172. [OutputMapping{
  173. <NameSpace>.<VarName>[.<Swizzle>] = <OutputVariableName>[.<Swizzle>] [: <MappingCondition>]
  174. [...]
  175. }]
  176. }
  177. ----
  178. * +++<u>ShaderNode</u>+++ the shader node block
  179. ** *ShaderNodeName* the name of this shader node, can be anything, but has to be *unique* in the shader scope.
  180. * +++<u>Definition</u>+++ : a reference to the shader node definition.
  181. ** *DefinitionName* : the name of the definition this Node use. this definition can be declared in the same j3md or in its own j3sn file.
  182. ** *DefinitionPath* : in case the definition is declared in it's own j3sn file, you have to set the path to this file here.
  183. * +++<u>Condition</u>+++ a condition that dictates if the node is active or not.
  184. ** *ActivationCondition* : 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.
  185. For example, let's say we have a Color and ColorMap material parameter, this condition “Color || ColorMap will generate this statement :
  186. [source,java]
  187. ----
  188. #if defined(COLOR) || defined(COLORMAP)
  189. ...
  190. #endif
  191. ----
  192. * +++<u>InputMapping</u>+++ the wiring of the inputs of this node, coming from previous node's outputs or from built in glsl inputs.
  193. ** *InputVariableName* : the name of the variable to map as declared in the definition.
  194. ** *Swizzle* : Swizling for the preceding variable. More information on glsl swizzling on this page link:https://www.khronos.org/opengl/wiki/GLSL_Type[https://www.khronos.org/opengl/wiki/GLSL_Type].
  195. ** *NameSpace* : The generator will use variable name space to avoid collision between variable names. Name space can be one of these values :
  196. *** *MatParam* : the following variable is a Material Parameter declared in the MaterialParameters block of the materialDefinition.
  197. *** *WorldParam* : 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 : link: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]
  198. *** *Attr* : the following variable is a shader attribute. It can be one those declared in the Type enum of the VertexBuffer class link: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].
  199. *** *Global* : 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've been found in the declaration to the shader output. *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*.
  200. *** *The name of a previous shader node* : 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.
  201. ** *VarName* : the name of the variable to assign to the input. This variable must be known in name space declared before.
  202. ** *MappingCondition* : Follows the same rules as the activation condition for the shaderNode, this mapping will be embed in a #ifdef statement n the resulting shader.
  203. * +++<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.
  204. ** *NameSpace* : the name space of the output to assign, this can only be “Global here.
  205. ** *VarName* : the name of a global output (can be anything, just be aware that 2 different names result in 2 different outputs).
  206. ** *OutputVariable* : Must be an output of the current node's definition.
  207. ** *MappingCondition* : Same as before.
  208. == Complete material definition and Shader Nodes example
  209. Here is an example of a very simple Material definition that just displays a solid color (controlled by a material parameter) on a mesh.
  210. [IMPORTANT]
  211. ====
  212. 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.
  213. ====
  214. [source,java]
  215. ----
  216. MaterialDef Simple {
  217. MaterialParameters {
  218. Color Color
  219. }
  220. Technique {
  221. WorldParameters {
  222. WorldViewProjectionMatrix
  223. }
  224. VertexShaderNodes {
  225. ShaderNode CommonVert {
  226. Definition : CommonVert : Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn
  227. InputMappings {
  228. worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix
  229. modelPosition = Global.position.xyz
  230. }
  231. OutputMappings {
  232. Global.position = projPosition
  233. }
  234. }
  235. }
  236. FragmentShaderNodes {
  237. ShaderNode ColorMult {
  238. Definition : ColorMult : Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn
  239. InputMappings {
  240. color1 = MatParam.Color
  241. color2 = Global.color
  242. }
  243. OutputMappings {
  244. Global.color = outColor
  245. }
  246. }
  247. }
  248. }
  249. }
  250. ----
  251. This Material definition has one Default technique with 2 node declarations. +
  252. *+++<u>CommonVert Definition</u>+++* +
  253. 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. +
  254. Here is the definition content (Common/MatDefs/ShaderNodes/Common/CommonVert.j3sn) :
  255. [source,java]
  256. ----
  257. ShaderNodesDefinitions {
  258. ShaderNodeDefinition CommonVert {
  259. Type: Vertex
  260. Shader GLSL100: Common/MatDefs/ShaderNodes/Common/commonVert.vert
  261. Documentation {
  262. This Node is responsible for computing vertex position in projection space.
  263. It also can pass texture coordinates 1 & 2, and vertexColor to the frgment shader as varying (or inputs for glsl >=1.3)
  264. @input modelPosition the vertex position in model space (usually assigned with Attr.inPosition or Global.position)
  265. @input worldViewProjectionMatrix the World View Projection Matrix transforms model space to projection space.
  266. @input texCoord1 The first texture coordinates of the vertex (usually assigned with Attr.inTexCoord)
  267. @input texCoord2 The second texture coordinates of the vertex (usually assigned with Attr.inTexCoord2)
  268. @input vertColor The color of the vertex (usually assigned with Attr.inColor)
  269. @output projPosition Position of the vertex in projection space.(usually assigned to Global.position)
  270. @output vec2 texCoord1 The first texture coordinates of the vertex (output as a varying)
  271. @output vec2 texCoord2 The second texture coordinates of the vertex (output as a varying)
  272. @output vec4 vertColor The color of the vertex (output as a varying)
  273. }
  274. Input{
  275. vec3 modelPosition
  276. mat4 worldViewProjectionMatrix
  277. vec2 texCoord1
  278. vec2 texCoord2
  279. vec4 vertColor
  280. }
  281. Output{
  282. vec4 projPosition
  283. vec2 texCoord1
  284. vec2 texCoord2
  285. vec4 vertColor
  286. }
  287. }
  288. }
  289. ----
  290. [TIP]
  291. ====
  292. Note that texCoord1/2 and vertColor are declared both as input and output. The generator will use the same variables for them.
  293. ====
  294. Here is the shader Node code ( Common/MatDefs/ShaderNodes/Common/commonVert.vert).
  295. [source,java]
  296. ----
  297. void main(){
  298. projPosition = worldViewProjectionMatrix * vec4(modelPosition, 1.0);
  299. }
  300. ----
  301. As you can see all the inputs and outputs are not used. That'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.
  302. *+++<u>CommonVert input mapping</u>+++* +
  303. 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 :
  304. * *worldViewProjectionMatrix = WorldParam.WorldViewProjectionMatrix* : the input parameter worldViewProjectionMatrix is assigned with the WorldViewProjectionMatrix World parameter declared in the WorlParameters block of the technique.
  305. * *modelPosition = Global.position.xyz* : the modelPosition (understand the vertex position in the model coordinate space) is assigned with the Global position variable.
  306. [TIP]
  307. ====
  308. As mentioned before Global position is initialized with the attribute inPosition, so this is equivalent to :
  309. [source, java]
  310. ----
  311. modelPosition = Attr.inPosition.xyz
  312. ----
  313. ====
  314. [TIP]
  315. ====
  316. 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.
  317. ====
  318. *+++<u>CommonVert output mapping</u>+++* +
  319. * *Global.position = projPosition* : The result of the multiplication of the worldViewProjectionMatrix and the modelPosition is assigned to the Globale position.
  320. [TIP]
  321. ====
  322. The Global.position variable will be assigned to the gl_Position glsl built in output at the end of the shader.
  323. ====
  324. *+++<u>ColorMult Definition</u>+++* +
  325. ColorMult is a very basic Shader Node that takes two colors as input and multiply them.
  326. Here is the definition content (Common/MatDefs/ShaderNodes/Basic/ColorMult.j3sn) :
  327. [source,java]
  328. ----
  329. ShaderNodeDefinitions{
  330. ShaderNodeDefinition ColorMult {
  331. Type: Fragment
  332. Shader GLSL100: Common/MatDefs/ShaderNodes/Basic/colorMult.frag
  333. Documentation{
  334. Multiplies two colors
  335. @input color1 the first color
  336. @input color2 the second color
  337. @output outColor the resulting color
  338. }
  339. Input {
  340. vec4 color1
  341. vec4 color2
  342. }
  343. Output {
  344. vec4 outColor
  345. }
  346. }
  347. }
  348. ----
  349. Here is the shader Node code (Common/MatDefs/ShaderNodes/Basic/colorMult.frag).
  350. [source,java]
  351. ----
  352. void main(){
  353. outColor = color1 * color2;
  354. }
  355. ----
  356. *+++<u>ColorMult input mapping</u>+++* +
  357. All inputs are mapped here :
  358. * *color1 = MatParam.Color* : The first color is assigned to the Color Material parameter declared in the MaterialParameter block of the material definition.
  359. * *color2 = Global.color* : The second color is assigned with the Global color variable. this is defaulted to vec4(1.0) (opaque white).
  360. [NOTE]
  361. ====
  362. In a very complex material def this variable could already have been assigned with a previous Shader Node output.
  363. ====
  364. *+++<u>ColorMult output mapping</u>+++* +
  365. * *Global.color = outColor* : the resulting color is assigned to the Global color variable.
  366. [TIP]
  367. ====
  368. Note that the Global.color variable will be assigned to gl_FragColor (glsl < 1.5) or declared as a Global ouput of the shader (glsl >= 1.5).
  369. ====
  370. [TIP]
  371. ====
  372. Also note that in case several Global variables are declared, the generator will assign them gl_FragData[i](glsl < 1.5) i being the order the variable has been found in the material def. For glsl >= 1.5 the veriable will just all be declared as shader output in the order they've been found in the declaration.
  373. ====
  374. *+++<u>Generated shader code</u>+++*
  375. [IMPORTANT]
  376. ====
  377. Don't take this code as carved in stone, the generated code can change as optimization of the shader generator goes on.
  378. ====
  379. Vertex Shader (glsl 1.0)
  380. [source,java]
  381. ----
  382. uniform mat4 g_WorldViewProjectionMatrix;
  383. attribute vec4 inPosition;
  384. void main(){
  385. vec4 Global_position = inPosition;
  386. //CommonVert : Begin
  387. vec3 CommonVert_modelPosition = Global_position.xyz;
  388. vec4 CommonVert_projPosition;
  389. vec2 CommonVert_texCoord1;
  390. vec2 CommonVert_texCoord2;
  391. vec4 CommonVert_vertColor;
  392. CommonVert_projPosition = g_WorldViewProjectionMatrix * vec4(CommonVert_modelPosition, 1.0);
  393. Global_position = CommonVert_projPosition;
  394. //CommonVert : End
  395. gl_Position = Global_position;
  396. }
  397. ----
  398. All materials parameter, world parameters, attributes varying are declared first. then for each shader node, the declarative part is appended. +
  399. For the main function, for each shader node, the input mappings are declared and assigned, the output are declared. +
  400. 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. +
  401. Then, the output are mapped.
  402. As you can see texCoord1/2 and vertColor are declared but never used. That'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.
  403. Note that most glsl compiler will optimize this when compiling the shader on the GPU.
  404. Fragment Shader (glsl 1.0)
  405. [source,java]
  406. ----
  407. uniform vec4 m_Color;
  408. void main(){
  409. vec4 Global_color = vec4(1.0);
  410. //ColorMult : Begin
  411. vec4 ColorMult_color2 = Global_color;
  412. vec4 ColorMult_outColor;
  413. ColorMult_outColor = m_Color * ColorMult_color2;
  414. Global_color = ColorMult_outColor;
  415. //ColorMult : End
  416. gl_FragColor = Global_color;
  417. }
  418. ----
  419. Same as for the Vertex shader. Note that the color1 is not declared, because it's directly replaced by the material parameter.
  420. [IMPORTANT]
  421. ====
  422. 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.
  423. ====
  424. For more explanations and design decisions please refer to the +++<abbr title="specification">spec</abbr>+++ here
  425. link: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].
  426. Thank you for the brave ones that came through all this reading. I'm not gonna offer you a prize in exchange of a password, because we ran out of JME thongs…