WGSLNodeFunction.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import NodeFunction from '../../../nodes/core/NodeFunction.js';
  2. import NodeFunctionInput from '../../../nodes/core/NodeFunctionInput.js';
  3. const declarationRegexp = /^[fn]*\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*[\-\>]*\s*([a-z_0-9]+)?/i;
  4. const propertiesRegexp = /([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/ig;
  5. const wgslTypeLib = {
  6. 'f32': 'float',
  7. 'i32': 'int',
  8. 'u32': 'uint',
  9. 'bool': 'bool',
  10. 'vec2<f32>': 'vec2',
  11. 'vec2<i32>': 'ivec2',
  12. 'vec2<u32>': 'uvec2',
  13. 'vec2<bool>': 'bvec2',
  14. 'vec3<f32>': 'vec3',
  15. 'vec3<i32>': 'ivec3',
  16. 'vec3<u32>': 'uvec3',
  17. 'vec3<bool>': 'bvec3',
  18. 'vec4<f32>': 'vec4',
  19. 'vec4<i32>': 'ivec4',
  20. 'vec4<u32>': 'uvec4',
  21. 'vec4<bool>': 'bvec4',
  22. 'mat2x2<f32>': 'mat2',
  23. 'mat2x2<i32>': 'imat2',
  24. 'mat2x2<u32>': 'umat2',
  25. 'mat2x2<bool>': 'bmat2',
  26. 'mat3x3<f32>': 'mat3',
  27. 'mat3x3<i32>': 'imat3',
  28. 'mat3x3<u32>': 'umat3',
  29. 'mat3x3<bool>': 'bmat3',
  30. 'mat4x4<f32>': 'mat4',
  31. 'mat4x4<i32>': 'imat4',
  32. 'mat4x4<u32>': 'umat4',
  33. 'mat4x4<bool>': 'bmat4'
  34. };
  35. const parse = ( source ) => {
  36. source = source.trim();
  37. const declaration = source.match( declarationRegexp );
  38. if ( declaration !== null && declaration.length === 4 ) {
  39. const inputsCode = declaration[ 2 ];
  40. const propsMatches = [];
  41. let match = null;
  42. while ( ( match = propertiesRegexp.exec( inputsCode ) ) !== null ) {
  43. propsMatches.push( { name: match[ 1 ], type: match[ 2 ] } );
  44. }
  45. // Process matches to correctly pair names and types
  46. const inputs = [];
  47. for ( let i = 0; i < propsMatches.length; i ++ ) {
  48. const { name, type } = propsMatches[ i ];
  49. let resolvedType = type;
  50. if ( resolvedType.startsWith( 'texture' ) ) {
  51. resolvedType = type.split( '<' )[ 0 ];
  52. }
  53. resolvedType = wgslTypeLib[ resolvedType ] || resolvedType;
  54. inputs.push( new NodeFunctionInput( resolvedType, name ) );
  55. }
  56. const blockCode = source.substring( declaration[ 0 ].length );
  57. const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : '';
  58. const type = declaration[ 3 ] || 'void';
  59. return {
  60. type,
  61. inputs,
  62. name,
  63. inputsCode,
  64. blockCode
  65. };
  66. } else {
  67. throw new Error( 'FunctionNode: Function is not a WGSL code.' );
  68. }
  69. };
  70. class WGSLNodeFunction extends NodeFunction {
  71. constructor( source ) {
  72. const { type, inputs, name, inputsCode, blockCode } = parse( source );
  73. super( type, inputs, name );
  74. this.inputsCode = inputsCode;
  75. this.blockCode = blockCode;
  76. }
  77. getCode( name = this.name ) {
  78. const type = this.type !== 'void' ? '-> ' + this.type : '';
  79. return `fn ${ name } ( ${ this.inputsCode.trim() } ) ${ type }` + this.blockCode;
  80. }
  81. }
  82. export default WGSLNodeFunction;