NodeKeywords.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. import VarNode from './VarNode.js';
  2. import PropertyNode from './PropertyNode.js';
  3. import PositionNode from '../accessors/PositionNode.js';
  4. import NormalNode from '../accessors/NormalNode.js';
  5. import { PI, RECIPROCAL_PI, EPSILON } from '../consts/MathConsts.js';
  6. import { saturateMacro, whiteComplementMacro } from '../functions/MathFunctions.js';
  7. class NodeKeywords {
  8. static PI = 'PI';
  9. static RECIPROCAL_PI = 'RECIPROCAL_PI';
  10. static EPSILON = 'EPSILON';
  11. static Saturate = 'saturate';
  12. static WhiteComplement = 'whiteComplement';
  13. static PositionLocal = 'PositionLocal';
  14. static PositionWorld = 'PositionWorld';
  15. static PositionView = 'PositionView';
  16. static PositionViewDirection = 'PositionViewDirection';
  17. static NormalLocal = 'NormalLocal';
  18. static NormalWorld = 'NormalWorld';
  19. static NormalView = 'NormalView';
  20. static Irradiance = 'Irradiance';
  21. static ReflectedLightIndirectDiffuse = 'ReflectedLightIndirectDiffuse';
  22. static ReflectedLightIndirectSpecular = 'ReflectedLightIndirectSpecular';
  23. static ReflectedLightDirectDiffuse = 'ReflectedLightDirectDiffuse';
  24. static ReflectedLightDirectSpecular = 'ReflectedLightDirectSpecular';
  25. static MaterialDiffuseColor = 'MaterialDiffuseColor';
  26. // STANDARD
  27. static MaterialRoughness = 'MaterialRoughness';
  28. static MaterialMetalness = 'MaterialMetalness';
  29. static MaterialSpecularTint = 'MaterialSpecularTint';
  30. constructor() {
  31. this.keywords = [
  32. // consts
  33. NodeKeywords.PI,
  34. NodeKeywords.RECIPROCAL_PI,
  35. NodeKeywords.EPSILON,
  36. // variadic macros
  37. NodeKeywords.Saturate,
  38. NodeKeywords.WhiteComplement,
  39. // nodes
  40. NodeKeywords.PositionLocal,
  41. NodeKeywords.PositionWorld,
  42. NodeKeywords.PositionView,
  43. NodeKeywords.PositionViewDirection,
  44. NodeKeywords.NormalLocal,
  45. NodeKeywords.NormalWorld,
  46. NodeKeywords.NormalView,
  47. // vars -> float
  48. NodeKeywords.MaterialRoughness,
  49. NodeKeywords.MaterialMetalness,
  50. // vars -> vec3
  51. NodeKeywords.Irradiance,
  52. NodeKeywords.ReflectedLightIndirectDiffuse,
  53. NodeKeywords.ReflectedLightIndirectSpecular,
  54. NodeKeywords.ReflectedLightDirectDiffuse,
  55. NodeKeywords.ReflectedLightDirectSpecular,
  56. NodeKeywords.MaterialSpecularTint,
  57. // vars -> vec4
  58. NodeKeywords.MaterialDiffuseColor
  59. ];
  60. this.nodes = [];
  61. this.keywordsCallback = {};
  62. }
  63. getNode( name ) {
  64. let node = this.nodes[ name ];
  65. if ( node === undefined ) {
  66. if ( this.keywordsCallback[ name ] !== undefined ) {
  67. node = this.keywordsCallback[ name ]( name );
  68. this.nodes[ name ] = node;
  69. return node;
  70. }
  71. switch ( name ) {
  72. case NodeKeywords.PI:
  73. node = PI;
  74. break;
  75. case NodeKeywords.RECIPROCAL_PI:
  76. node = RECIPROCAL_PI;
  77. break;
  78. case NodeKeywords.EPSILON:
  79. node = EPSILON;
  80. break;
  81. case NodeKeywords.Saturate:
  82. node = saturateMacro;
  83. break;
  84. case NodeKeywords.WhiteComplement:
  85. node = whiteComplementMacro;
  86. break;
  87. case NodeKeywords.PositionLocal:
  88. node = new VarNode( new PositionNode( PositionNode.GEOMETRY ), name );
  89. break;
  90. case NodeKeywords.PositionWorld:
  91. node = new VarNode( new PositionNode( PositionNode.WORLD ), name );
  92. break;
  93. case NodeKeywords.PositionView:
  94. node = new VarNode( new PositionNode( PositionNode.VIEW ), name );
  95. break;
  96. case NodeKeywords.PositionViewDirection:
  97. node = new VarNode( new PositionNode( PositionNode.VIEW_DIRECTION ), name );
  98. break;
  99. case NodeKeywords.NormalLocal:
  100. node = new VarNode( new NormalNode( NormalNode.GEOMETRY ), name );
  101. break;
  102. case NodeKeywords.NormalWorld:
  103. node = new VarNode( new NormalNode( NormalNode.WORLD ), name );
  104. break;
  105. case NodeKeywords.NormalView:
  106. node = new VarNode( new NormalNode( NormalNode.VIEW ), name );
  107. break;
  108. // floats properties
  109. case NodeKeywords.MaterialRoughness:
  110. case NodeKeywords.MaterialMetalness:
  111. node = new PropertyNode( name, 'float' );
  112. break;
  113. // vec3 properties
  114. case NodeKeywords.Irradiance:
  115. case NodeKeywords.ReflectedLightIndirectDiffuse:
  116. case NodeKeywords.ReflectedLightIndirectSpecular:
  117. case NodeKeywords.ReflectedLightDirectDiffuse:
  118. case NodeKeywords.ReflectedLightDirectSpecular:
  119. case NodeKeywords.MaterialSpecularTint:
  120. node = new PropertyNode( name, 'vec3' );
  121. break;
  122. // vec4 properties
  123. case NodeKeywords.MaterialDiffuseColor:
  124. node = new PropertyNode( name, 'vec4' );
  125. break;
  126. }
  127. if ( node !== undefined ) {
  128. this.nodes[ name ] = node;
  129. }
  130. }
  131. return node;
  132. }
  133. addKeyword( name, callback ) {
  134. this.keywords.push( name );
  135. this.keywordsCallback[ name ] = callback;
  136. return this;
  137. }
  138. parse( code ) {
  139. const keywordNames = this.keywords;
  140. const regExp = new RegExp( `\\b${keywordNames.join( '\\b|\\b' )}\\b`, 'g' );
  141. const codeKeywords = code.match( regExp );
  142. const keywords = [];
  143. if ( codeKeywords !== null ) {
  144. for ( const keyword of codeKeywords ) {
  145. const node = this.getNode( keyword );
  146. if ( keywords.indexOf( node ) === - 1 ) {
  147. keywords.push( node );
  148. }
  149. }
  150. }
  151. return keywords;
  152. }
  153. include( builder, code ) {
  154. const keywords = this.parse( code );
  155. for ( const keywordNode of keywords ) {
  156. keywordNode.build( builder );
  157. }
  158. }
  159. }
  160. export default NodeKeywords;