effectFallbacks.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { Nullable } from '../types';
  2. import { IEffectFallbacks } from './iEffectFallbacks';
  3. declare type Effect = import("./effect").Effect;
  4. declare type AbstractMesh = import("../Meshes/abstractMesh").AbstractMesh;
  5. /**
  6. * EffectFallbacks can be used to add fallbacks (properties to disable) to certain properties when desired to improve performance.
  7. * (Eg. Start at high quality with reflection and fog, if fps is low, remove reflection, if still low remove fog)
  8. */
  9. export class EffectFallbacks implements IEffectFallbacks {
  10. private _defines: { [key: string]: Array<String> } = {};
  11. private _currentRank = 32;
  12. private _maxRank = -1;
  13. private _mesh: Nullable<AbstractMesh> = null;
  14. /**
  15. * Removes the fallback from the bound mesh.
  16. */
  17. public unBindMesh() {
  18. this._mesh = null;
  19. }
  20. /**
  21. * Adds a fallback on the specified property.
  22. * @param rank The rank of the fallback (Lower ranks will be fallbacked to first)
  23. * @param define The name of the define in the shader
  24. */
  25. public addFallback(rank: number, define: string): void {
  26. if (!this._defines[rank]) {
  27. if (rank < this._currentRank) {
  28. this._currentRank = rank;
  29. }
  30. if (rank > this._maxRank) {
  31. this._maxRank = rank;
  32. }
  33. this._defines[rank] = new Array<String>();
  34. }
  35. this._defines[rank].push(define);
  36. }
  37. /**
  38. * Sets the mesh to use CPU skinning when needing to fallback.
  39. * @param rank The rank of the fallback (Lower ranks will be fallbacked to first)
  40. * @param mesh The mesh to use the fallbacks.
  41. */
  42. public addCPUSkinningFallback(rank: number, mesh: AbstractMesh) {
  43. this._mesh = mesh;
  44. if (rank < this._currentRank) {
  45. this._currentRank = rank;
  46. }
  47. if (rank > this._maxRank) {
  48. this._maxRank = rank;
  49. }
  50. }
  51. /**
  52. * Checks to see if more fallbacks are still availible.
  53. */
  54. public get hasMoreFallbacks(): boolean {
  55. return this._currentRank <= this._maxRank;
  56. }
  57. /**
  58. * Removes the defines that should be removed when falling back.
  59. * @param currentDefines defines the current define statements for the shader.
  60. * @param effect defines the current effect we try to compile
  61. * @returns The resulting defines with defines of the current rank removed.
  62. */
  63. public reduce(currentDefines: string, effect: Effect): string {
  64. // First we try to switch to CPU skinning
  65. if (this._mesh && this._mesh.computeBonesUsingShaders && this._mesh.numBoneInfluencers > 0) {
  66. this._mesh.computeBonesUsingShaders = false;
  67. currentDefines = currentDefines.replace("#define NUM_BONE_INFLUENCERS " + this._mesh.numBoneInfluencers, "#define NUM_BONE_INFLUENCERS 0");
  68. effect._bonesComputationForcedToCPU = true;
  69. var scene = this._mesh.getScene();
  70. for (var index = 0; index < scene.meshes.length; index++) {
  71. var otherMesh = scene.meshes[index];
  72. if (!otherMesh.material) {
  73. if (!this._mesh.material && otherMesh.computeBonesUsingShaders && otherMesh.numBoneInfluencers > 0) {
  74. otherMesh.computeBonesUsingShaders = false;
  75. }
  76. continue;
  77. }
  78. if (!otherMesh.computeBonesUsingShaders || otherMesh.numBoneInfluencers === 0) {
  79. continue;
  80. }
  81. if (otherMesh.material.getEffect() === effect) {
  82. otherMesh.computeBonesUsingShaders = false;
  83. } else if (otherMesh.subMeshes) {
  84. for (var subMesh of otherMesh.subMeshes) {
  85. let subMeshEffect = subMesh.effect;
  86. if (subMeshEffect === effect) {
  87. otherMesh.computeBonesUsingShaders = false;
  88. break;
  89. }
  90. }
  91. }
  92. }
  93. }
  94. else {
  95. var currentFallbacks = this._defines[this._currentRank];
  96. if (currentFallbacks) {
  97. for (var index = 0; index < currentFallbacks.length; index++) {
  98. currentDefines = currentDefines.replace("#define " + currentFallbacks[index], "");
  99. }
  100. }
  101. this._currentRank++;
  102. }
  103. return currentDefines;
  104. }
  105. }