babylon.sceneOptimizer.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. var __extends = this.__extends || function (d, b) {
  2. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  3. function __() { this.constructor = d; }
  4. __.prototype = b.prototype;
  5. d.prototype = new __();
  6. };
  7. var BABYLON;
  8. (function (BABYLON) {
  9. // Standard optimizations
  10. var SceneOptimization = (function () {
  11. function SceneOptimization(priority) {
  12. if (typeof priority === "undefined") { priority = 0; }
  13. this.priority = priority;
  14. this.apply = function (scene) {
  15. return true;
  16. };
  17. }
  18. return SceneOptimization;
  19. })();
  20. BABYLON.SceneOptimization = SceneOptimization;
  21. var TextureOptimization = (function (_super) {
  22. __extends(TextureOptimization, _super);
  23. function TextureOptimization(priority, maximumSize) {
  24. if (typeof priority === "undefined") { priority = 0; }
  25. if (typeof maximumSize === "undefined") { maximumSize = 1024; }
  26. var _this = this;
  27. _super.call(this, priority);
  28. this.priority = priority;
  29. this.maximumSize = maximumSize;
  30. this.apply = function (scene) {
  31. var allDone = true;
  32. for (var index = 0; index < scene.textures.length; index++) {
  33. var texture = scene.textures[index];
  34. if (!texture.canRescale) {
  35. continue;
  36. }
  37. var currentSize = texture.getSize();
  38. var maxDimension = Math.max(currentSize.width, currentSize.height);
  39. if (maxDimension > _this.maximumSize) {
  40. texture.scale(0.5);
  41. allDone = false;
  42. }
  43. }
  44. return allDone;
  45. };
  46. }
  47. return TextureOptimization;
  48. })(SceneOptimization);
  49. BABYLON.TextureOptimization = TextureOptimization;
  50. var HardwareScalingOptimization = (function (_super) {
  51. __extends(HardwareScalingOptimization, _super);
  52. function HardwareScalingOptimization(priority, maximumScale) {
  53. if (typeof priority === "undefined") { priority = 0; }
  54. if (typeof maximumScale === "undefined") { maximumScale = 2; }
  55. var _this = this;
  56. _super.call(this, priority);
  57. this.priority = priority;
  58. this.maximumScale = maximumScale;
  59. this._currentScale = 1;
  60. this.apply = function (scene) {
  61. _this._currentScale++;
  62. scene.getEngine().setHardwareScalingLevel(_this._currentScale);
  63. return _this._currentScale >= _this.maximumScale;
  64. };
  65. }
  66. return HardwareScalingOptimization;
  67. })(SceneOptimization);
  68. BABYLON.HardwareScalingOptimization = HardwareScalingOptimization;
  69. var ShadowsOptimization = (function (_super) {
  70. __extends(ShadowsOptimization, _super);
  71. function ShadowsOptimization() {
  72. _super.apply(this, arguments);
  73. this.apply = function (scene) {
  74. scene.shadowsEnabled = false;
  75. return true;
  76. };
  77. }
  78. return ShadowsOptimization;
  79. })(SceneOptimization);
  80. BABYLON.ShadowsOptimization = ShadowsOptimization;
  81. var PostProcessesOptimization = (function (_super) {
  82. __extends(PostProcessesOptimization, _super);
  83. function PostProcessesOptimization() {
  84. _super.apply(this, arguments);
  85. this.apply = function (scene) {
  86. scene.postProcessesEnabled = false;
  87. return true;
  88. };
  89. }
  90. return PostProcessesOptimization;
  91. })(SceneOptimization);
  92. BABYLON.PostProcessesOptimization = PostProcessesOptimization;
  93. var LensFlaresOptimization = (function (_super) {
  94. __extends(LensFlaresOptimization, _super);
  95. function LensFlaresOptimization() {
  96. _super.apply(this, arguments);
  97. this.apply = function (scene) {
  98. scene.lensFlaresEnabled = false;
  99. return true;
  100. };
  101. }
  102. return LensFlaresOptimization;
  103. })(SceneOptimization);
  104. BABYLON.LensFlaresOptimization = LensFlaresOptimization;
  105. var ParticlesOptimization = (function (_super) {
  106. __extends(ParticlesOptimization, _super);
  107. function ParticlesOptimization() {
  108. _super.apply(this, arguments);
  109. this.apply = function (scene) {
  110. scene.particlesEnabled = false;
  111. return true;
  112. };
  113. }
  114. return ParticlesOptimization;
  115. })(SceneOptimization);
  116. BABYLON.ParticlesOptimization = ParticlesOptimization;
  117. var RenderTargetsOptimization = (function (_super) {
  118. __extends(RenderTargetsOptimization, _super);
  119. function RenderTargetsOptimization() {
  120. _super.apply(this, arguments);
  121. this.apply = function (scene) {
  122. scene.renderTargetsEnabled = false;
  123. return true;
  124. };
  125. }
  126. return RenderTargetsOptimization;
  127. })(SceneOptimization);
  128. BABYLON.RenderTargetsOptimization = RenderTargetsOptimization;
  129. var MergeMeshesOptimization = (function (_super) {
  130. __extends(MergeMeshesOptimization, _super);
  131. function MergeMeshesOptimization() {
  132. _super.apply(this, arguments);
  133. var _this = this;
  134. this._canBeMerged = function (abstractMesh) {
  135. if (!(abstractMesh instanceof BABYLON.Mesh)) {
  136. return false;
  137. }
  138. var mesh = abstractMesh;
  139. if (!mesh.isVisible || !mesh.isEnabled()) {
  140. return false;
  141. }
  142. if (mesh.instances.length > 0) {
  143. return false;
  144. }
  145. if (mesh.skeleton || mesh.hasLODLevels) {
  146. return false;
  147. }
  148. return true;
  149. };
  150. this.apply = function (scene) {
  151. var globalPool = scene.meshes.slice(0);
  152. var globalLength = globalPool.length;
  153. for (var index = 0; index < globalLength; index++) {
  154. var currentPool = new Array();
  155. var current = globalPool[index];
  156. // Checks
  157. if (!_this._canBeMerged(current)) {
  158. continue;
  159. }
  160. currentPool.push(current);
  161. for (var subIndex = index + 1; subIndex < globalLength; subIndex++) {
  162. var otherMesh = globalPool[subIndex];
  163. if (!_this._canBeMerged(otherMesh)) {
  164. continue;
  165. }
  166. if (otherMesh.material !== current.material) {
  167. continue;
  168. }
  169. if (otherMesh.checkCollisions !== current.checkCollisions) {
  170. continue;
  171. }
  172. currentPool.push(otherMesh);
  173. globalLength--;
  174. globalPool.splice(subIndex, 1);
  175. subIndex--;
  176. }
  177. if (currentPool.length < 2) {
  178. continue;
  179. }
  180. // Merge meshes
  181. BABYLON.Mesh.MergeMeshes(currentPool);
  182. }
  183. return true;
  184. };
  185. }
  186. return MergeMeshesOptimization;
  187. })(SceneOptimization);
  188. BABYLON.MergeMeshesOptimization = MergeMeshesOptimization;
  189. // Options
  190. var SceneOptimizerOptions = (function () {
  191. function SceneOptimizerOptions(targetFrameRate, trackerDuration) {
  192. if (typeof targetFrameRate === "undefined") { targetFrameRate = 60; }
  193. if (typeof trackerDuration === "undefined") { trackerDuration = 2000; }
  194. this.targetFrameRate = targetFrameRate;
  195. this.trackerDuration = trackerDuration;
  196. this.optimizations = new Array();
  197. }
  198. SceneOptimizerOptions.LowDegradationAllowed = function (targetFrameRate) {
  199. var result = new SceneOptimizerOptions(targetFrameRate);
  200. var priority = 0;
  201. result.optimizations.push(new MergeMeshesOptimization(priority));
  202. result.optimizations.push(new ShadowsOptimization(priority));
  203. result.optimizations.push(new LensFlaresOptimization(priority));
  204. // Next priority
  205. priority++;
  206. result.optimizations.push(new PostProcessesOptimization(priority));
  207. result.optimizations.push(new ParticlesOptimization(priority));
  208. // Next priority
  209. priority++;
  210. result.optimizations.push(new TextureOptimization(priority, 1024));
  211. return result;
  212. };
  213. SceneOptimizerOptions.ModerateDegradationAllowed = function (targetFrameRate) {
  214. var result = new SceneOptimizerOptions(targetFrameRate);
  215. var priority = 0;
  216. result.optimizations.push(new MergeMeshesOptimization(priority));
  217. result.optimizations.push(new ShadowsOptimization(priority));
  218. result.optimizations.push(new LensFlaresOptimization(priority));
  219. // Next priority
  220. priority++;
  221. result.optimizations.push(new PostProcessesOptimization(priority));
  222. result.optimizations.push(new ParticlesOptimization(priority));
  223. // Next priority
  224. priority++;
  225. result.optimizations.push(new TextureOptimization(priority, 512));
  226. // Next priority
  227. priority++;
  228. result.optimizations.push(new RenderTargetsOptimization(priority));
  229. // Next priority
  230. priority++;
  231. result.optimizations.push(new HardwareScalingOptimization(priority, 2));
  232. return result;
  233. };
  234. SceneOptimizerOptions.HighDegradationAllowed = function (targetFrameRate) {
  235. var result = new SceneOptimizerOptions(targetFrameRate);
  236. var priority = 0;
  237. result.optimizations.push(new MergeMeshesOptimization(priority));
  238. result.optimizations.push(new ShadowsOptimization(priority));
  239. result.optimizations.push(new LensFlaresOptimization(priority));
  240. // Next priority
  241. priority++;
  242. result.optimizations.push(new PostProcessesOptimization(priority));
  243. result.optimizations.push(new ParticlesOptimization(priority));
  244. // Next priority
  245. priority++;
  246. result.optimizations.push(new TextureOptimization(priority, 256));
  247. // Next priority
  248. priority++;
  249. result.optimizations.push(new RenderTargetsOptimization(priority));
  250. // Next priority
  251. priority++;
  252. result.optimizations.push(new HardwareScalingOptimization(priority, 4));
  253. return result;
  254. };
  255. return SceneOptimizerOptions;
  256. })();
  257. BABYLON.SceneOptimizerOptions = SceneOptimizerOptions;
  258. // Scene optimizer tool
  259. var SceneOptimizer = (function () {
  260. function SceneOptimizer() {
  261. }
  262. SceneOptimizer._CheckCurrentState = function (scene, options, currentPriorityLevel, onSuccess, onFailure) {
  263. // TODO: add an epsilon
  264. if (scene.getEngine().getFps() >= options.targetFrameRate) {
  265. if (onSuccess) {
  266. onSuccess();
  267. }
  268. return;
  269. }
  270. // Apply current level of optimizations
  271. var allDone = true;
  272. var noOptimizationApplied = true;
  273. for (var index = 0; index < options.optimizations.length; index++) {
  274. var optimization = options.optimizations[index];
  275. if (optimization.priority === currentPriorityLevel) {
  276. noOptimizationApplied = false;
  277. allDone = allDone && optimization.apply(scene);
  278. }
  279. }
  280. // If no optimization was applied, this is a failure :(
  281. if (noOptimizationApplied) {
  282. if (onFailure) {
  283. onFailure();
  284. }
  285. return;
  286. }
  287. // If all optimizations were done, move to next level
  288. if (allDone) {
  289. currentPriorityLevel++;
  290. }
  291. // Let's the system running for a specific amount of time before checking FPS
  292. scene.executeWhenReady(function () {
  293. setTimeout(function () {
  294. SceneOptimizer._CheckCurrentState(scene, options, currentPriorityLevel, onSuccess, onFailure);
  295. }, options.trackerDuration);
  296. });
  297. };
  298. SceneOptimizer.OptimizeAsync = function (scene, options, onSuccess, onFailure) {
  299. if (!options) {
  300. options = SceneOptimizerOptions.ModerateDegradationAllowed();
  301. }
  302. // Let's the system running for a specific amount of time before checking FPS
  303. scene.executeWhenReady(function () {
  304. setTimeout(function () {
  305. SceneOptimizer._CheckCurrentState(scene, options, 0, onSuccess, onFailure);
  306. }, options.trackerDuration);
  307. });
  308. };
  309. return SceneOptimizer;
  310. })();
  311. BABYLON.SceneOptimizer = SceneOptimizer;
  312. })(BABYLON || (BABYLON = {}));
  313. //# sourceMappingURL=babylon.sceneOptimizer.js.map