NodeBuilder.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import NodeUniform from './NodeUniform.js';
  2. const VERSION = '1';
  3. class NodeBuilder {
  4. constructor( material, renderer ) {
  5. this.material = material;
  6. this.renderer = renderer;
  7. this.slots = { vertex: [], fragment: [] };
  8. this.defines = { vertex: {}, fragment: {} };
  9. this.uniforms = { vertex: [], fragment: [] };
  10. this.nodesData = new WeakMap();
  11. this.shaderStage = null;
  12. }
  13. addSlot( shader, slot ) {
  14. this.slots[ shader ].push( slot );
  15. }
  16. define( shader, name, value = '' ) {
  17. this.defines[ shader ][ name ] = value;
  18. }
  19. generateVec2( x, y ) {
  20. return `vec2( ${x}, ${y})`;
  21. }
  22. generateVec3( x, y, z ) {
  23. return `vec3( ${x}, ${y}, ${z} )`;
  24. }
  25. generateVec4( x, y, z, w ) {
  26. return `vec4( ${x}, ${y}, ${z}, ${w} )`;
  27. }
  28. generateFloat( value ) {
  29. return value + ( value % 1 ? '' : '.0' );
  30. }
  31. getUniformNSName( nodeUniform ) {
  32. return nodeUniform.name;
  33. }
  34. getTypeLength( type ) {
  35. if ( type === 'float' ) return 1;
  36. if ( type === 'vec2' ) return 2;
  37. if ( type === 'vec3' ) return 3;
  38. if ( type === 'vec4' ) return 4;
  39. return 0;
  40. }
  41. getDataFromNode( node, shaderStage = null ) {
  42. let nodeData = this.nodesData.get( node );
  43. if ( nodeData === undefined ) {
  44. nodeData = { vertex: {}, fragment: {} };
  45. this.nodesData.set( node, nodeData );
  46. }
  47. return shaderStage ? nodeData[ shaderStage ] : nodeData;
  48. }
  49. getUniformFromNode( node, shaderStage, type ) {
  50. const nodeData = this.getDataFromNode( node, shaderStage );
  51. let nodeUniform = nodeData.uniform;
  52. if ( nodeUniform === undefined ) {
  53. const uniforms = this.uniforms[shaderStage];
  54. const index = uniforms.length;
  55. nodeUniform = new NodeUniform( 'nodeU' + index, type, node );
  56. uniforms.push( nodeUniform );
  57. nodeData.uniform = nodeUniform;
  58. }
  59. return nodeUniform;
  60. }
  61. /*
  62. analyzeNode( node ) {
  63. }
  64. */
  65. flowNode( node, output ) {
  66. let flowData = {};
  67. flowData.result = node.build( this, output );
  68. return flowData;
  69. }
  70. buildDefines( shader ) {
  71. const defines = this.defines[ shader ];
  72. let code = '';
  73. for ( let name in defines ) {
  74. code += `#define ${name} ${defines[name]}\n`;
  75. }
  76. return code;
  77. }
  78. build( shaderStage ) {
  79. this.shaderStage = shaderStage;
  80. const slots = this.slots[ shaderStage ];
  81. const uniforms = this.uniforms[ shaderStage ];
  82. if ( slots.length ) {
  83. this.define( shaderStage, 'NODE', VERSION );
  84. for( let i = 0; i < slots.length; i++) {
  85. let slot = slots[i];
  86. let flowData = this.flowNode( slot.node, slot.output );
  87. this.define( shaderStage, `NODE_${slot.name}`, flowData.result );
  88. }
  89. let uniformsCode = '';
  90. for( let i = 0; i < uniforms.length; i++) {
  91. let uniform = uniforms[i];
  92. uniformsCode += `${uniform.type} ${uniform.name}; `;
  93. }
  94. this.define( shaderStage, 'NODE_UNIFORMS', uniformsCode );
  95. }
  96. let defines = this.buildDefines( shaderStage );
  97. return {
  98. defines
  99. };
  100. }
  101. format( code, fromType, toType ) {
  102. const typeToType = `${fromType} -> ${toType}`;
  103. switch ( typeToType ) {
  104. case 'float -> vec3' : return `vec3( ${code} )`;
  105. case 'vec3 -> float' : return `${code}.x`;
  106. }
  107. return code;
  108. }
  109. }
  110. export default NodeBuilder;