gulp-processShaders.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // Dependencies.
  2. var through = require('through2');
  3. var PluginError = require('plugin-error');
  4. let path = require('path');
  5. let fs = require('fs');
  6. /**
  7. * Template creating hidden ts file containing the shaders.
  8. */
  9. let tsShaderTemplate =
  10. `import { Effect } from "##EFFECTLOCATION_PLACEHOLDER##";
  11. ##INCLUDES_PLACEHOLDER##
  12. let name = '##NAME_PLACEHOLDER##';
  13. let shader = \`##SHADER_PLACEHOLDER##\`;
  14. Effect.##SHADERSTORE_PLACEHOLDER##[name] = shader;
  15. ##EXPORT_PLACEHOLDER##
  16. // tata
  17. `;
  18. /**
  19. * Get the shaders name from their path.
  20. */
  21. function getShaderName(filename) {
  22. let parts = filename.split('.');
  23. if (parts[1] !== 'fx') {
  24. return parts[0] + (parts[1] === 'fragment' ? 'Pixel' : 'Vertex') + "Shader";
  25. } else {
  26. return parts[0];
  27. }
  28. }
  29. /**
  30. * Get the shaders included in the current one to generate to proper imports.
  31. */
  32. function getIncludes(sourceCode) {
  33. var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
  34. var match = regex.exec(sourceCode);
  35. var includes = new Set();
  36. while (match != null) {
  37. let includeFile = match[1];
  38. // Uniform declaration
  39. if (includeFile.indexOf("__decl__") !== -1) {
  40. includeFile = includeFile.replace(/__decl__/, "");
  41. // Add non UBO import
  42. const noUBOFile = includeFile + "Declaration";
  43. includes.add(noUBOFile);
  44. includeFile = includeFile.replace(/Vertex/, "Ubo");
  45. includeFile = includeFile.replace(/Fragment/, "Ubo");
  46. const uBOFile = includeFile + "Declaration";
  47. includes.add(uBOFile);
  48. }
  49. else {
  50. includes.add(includeFile);
  51. }
  52. match = regex.exec(sourceCode);
  53. }
  54. return includes;
  55. }
  56. /**
  57. * Generate a ts file per shader file.
  58. */
  59. function main(isCore) {
  60. return through.obj(function (file, enc, cb) {
  61. if (file.isNull()) {
  62. cb(null, file);
  63. return;
  64. }
  65. if (file.isStream()) {
  66. cb(new PluginError("Process Shader", "Streaming not supported."));
  67. }
  68. const filename = path.basename(file.path);
  69. const normalized = path.normalize(file.path);
  70. const directory = path.dirname(normalized);
  71. const shaderName = getShaderName(filename);
  72. const tsFilename = filename.replace('.fx', '.ts');
  73. let fxData = file.contents.toString();
  74. // Remove Trailing whitespace...
  75. fxData = fxData.replace(/[^\S\r\n]+$/gm, "");
  76. // Generate imports for includes.
  77. let includeText = "";
  78. const includes = getIncludes(fxData);
  79. includes.forEach((entry) => {
  80. //entry = entry.replace(/(\/ShadersInclude)\1+/g, "/ShadersInclude");
  81. if (isCore) {
  82. includeText = includeText + `import "./ShadersInclude/${entry}";
  83. `;
  84. }
  85. else {
  86. includeText = includeText + `import "babylonjs/Shaders/ShadersInclude/${entry}";
  87. `;
  88. }
  89. });
  90. // Chose shader store.
  91. const isInclude = directory.indexOf("ShadersInclude") > -1;
  92. const shaderStore = isInclude ? "IncludesShadersStore" : "ShadersStore";
  93. let effectLocation;
  94. if (isCore) {
  95. if (isInclude) {
  96. effectLocation = "../../Materials/effect";
  97. includeText = includeText.replace(/ShadersInclude\//g, "");
  98. }
  99. else {
  100. effectLocation = "../Materials/effect";
  101. }
  102. }
  103. else {
  104. effectLocation = "babylonjs/Materials/effect";
  105. }
  106. // Fill template in.
  107. let tsContent = tsShaderTemplate.replace('##EFFECTLOCATION_PLACEHOLDER##', effectLocation);
  108. tsContent = tsContent.replace('##INCLUDES_PLACEHOLDER##', includeText);
  109. tsContent = tsContent.replace('##NAME_PLACEHOLDER##', shaderName);
  110. tsContent = tsContent.replace('##SHADER_PLACEHOLDER##', fxData);
  111. tsContent = tsContent.replace('##SHADERSTORE_PLACEHOLDER##', shaderStore);
  112. tsContent = tsContent.replace('##EXPORT_PLACEHOLDER##', `/** @hidden */
  113. export var ${shaderName} = { name, shader };`)
  114. // Go to disk.
  115. fs.writeFileSync(directory + '/' + tsFilename, tsContent);
  116. return cb();
  117. });
  118. }
  119. module.exports = main;