GLSLNodeFunction.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import NodeFunction from '../core/NodeFunction.js';
  2. import NodeFunctionInput from '../core/NodeFunctionInput.js';
  3. const declarationRegexp = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i;
  4. const propertiesRegexp = /[a-z_0-9]+/ig;
  5. const pragmaMain = '#pragma main';
  6. const parse = ( source ) => {
  7. source = source.trim();
  8. const pragmaMainIndex = source.indexOf( pragmaMain );
  9. const mainCode = pragmaMainIndex !== - 1 ? source.substr( pragmaMainIndex + pragmaMain.length ) : source;
  10. const declaration = mainCode.match( declarationRegexp );
  11. if ( declaration !== null && declaration.length === 5 ) {
  12. // tokenizer
  13. const inputsCode = declaration[ 4 ];
  14. const propsMatches = [];
  15. let nameMatch = null;
  16. while ( ( nameMatch = propertiesRegexp.exec( inputsCode ) ) !== null ) {
  17. propsMatches.push( nameMatch );
  18. }
  19. // parser
  20. const inputs = [];
  21. let i = 0;
  22. while ( i < propsMatches.length ) {
  23. const isConst = propsMatches[ i ][ 0 ] === 'const';
  24. if ( isConst === true ) {
  25. i ++;
  26. }
  27. let qualifier = propsMatches[ i ][ 0 ];
  28. if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) {
  29. i ++;
  30. } else {
  31. qualifier = '';
  32. }
  33. const type = propsMatches[ i ++ ][ 0 ];
  34. let count = Number.parseInt( propsMatches[ i ][ 0 ] );
  35. if ( Number.isNaN( count ) === false ) i ++;
  36. else count = null;
  37. const name = propsMatches[ i ++ ][ 0 ];
  38. inputs.push( new NodeFunctionInput( type, name, count, qualifier, isConst ) );
  39. }
  40. //
  41. const blockCode = mainCode.substring( declaration[ 0 ].length );
  42. const name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : '';
  43. const type = declaration[ 2 ];
  44. const presicion = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
  45. const headerCode = pragmaMainIndex !== - 1 ? source.substr( 0, pragmaMainIndex ) : '';
  46. return {
  47. type,
  48. inputs,
  49. name,
  50. presicion,
  51. inputsCode,
  52. blockCode,
  53. headerCode
  54. };
  55. } else {
  56. throw new Error( 'FunctionNode: Function is not a GLSL code.' );
  57. }
  58. };
  59. class GLSLNodeFunction extends NodeFunction {
  60. constructor( source ) {
  61. const { type, inputs, name, presicion, inputsCode, blockCode, headerCode } = parse( source );
  62. super( type, inputs, name, presicion );
  63. this.inputsCode = inputsCode;
  64. this.blockCode = blockCode;
  65. this.headerCode = headerCode;
  66. }
  67. getCode( name = this.name ) {
  68. const headerCode = this.headerCode;
  69. const presicion = this.presicion;
  70. let declarationCode = `${ this.type } ${ name } ( ${ this.inputsCode.trim() } )`;
  71. if ( presicion !== '' ) {
  72. declarationCode = `${ presicion } ${ declarationCode }`;
  73. }
  74. return headerCode + declarationCode + this.blockCode;
  75. }
  76. }
  77. export default GLSLNodeFunction;