babylon.postProcessRenderEffect.ts 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. module BABYLON {
  2. export class PostProcessRenderEffect {
  3. private _engine: Engine;
  4. private _postProcesses: PostProcess[];
  5. private _postProcessType; //The type must inherit from PostProcess (example: BABYLON.BlackAndWhitePostProcess, like this without quotes).
  6. private _ratio: number;
  7. private _samplingMode: number;
  8. private _singleInstance: boolean;
  9. private _cameras: Camera[];
  10. private _indicesForCamera: number[][];
  11. private _renderPasses: PostProcessRenderPass[];
  12. private _renderEffectAsPasses: PostProcessRenderEffect[];
  13. // private
  14. public _name: string;
  15. public parameters: (effect: Effect) => void;
  16. constructor(engine: Engine, name: string, postProcessType, ratio?: number, samplingMode?: number, singleInstance?: boolean) {
  17. this._engine = engine;
  18. this._name = name;
  19. this._postProcessType = postProcessType;
  20. this._ratio = ratio || 1.0;
  21. this._samplingMode = samplingMode || null;
  22. this._singleInstance = singleInstance || true;
  23. this._cameras = [];
  24. this._postProcesses = [];
  25. this._indicesForCamera = [];
  26. this._renderPasses = [];
  27. this._renderEffectAsPasses = [];
  28. this.parameters = (effect: Effect) => { };
  29. }
  30. private static _GetInstance(engine: Engine, postProcessType, ratio: number, samplingMode: number): PostProcess {
  31. var postProcess;
  32. var instance;
  33. var args = [];
  34. var parameters = PostProcessRenderEffect._GetParametersNames(postProcessType);
  35. for (var i = 0; i < parameters.length; i++) {
  36. switch (parameters[i]) {
  37. case "name":
  38. args[i] = postProcessType.toString();
  39. break;
  40. case "ratio":
  41. args[i] = ratio;
  42. break;
  43. case "camera":
  44. args[i] = null;
  45. break;
  46. case "samplingMode":
  47. args[i] = samplingMode;
  48. break;
  49. case "engine":
  50. args[i] = engine;
  51. break;
  52. case "reusable":
  53. args[i] = true;
  54. break;
  55. default:
  56. args[i] = null;
  57. break;
  58. }
  59. }
  60. postProcess = function () { };
  61. postProcess.prototype = postProcessType.prototype;
  62. instance = new postProcess();
  63. postProcessType.apply(instance, args);
  64. return instance;
  65. }
  66. private static _GetParametersNames(func): string[] {
  67. var commentsRegex = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
  68. var functWithoutComments = func.toString().replace(commentsRegex, '');
  69. var parameters = functWithoutComments.slice(functWithoutComments.indexOf('(') + 1, functWithoutComments.indexOf(')')).match(/([^\s,]+)/g);
  70. if (parameters === null)
  71. parameters = [];
  72. return parameters;
  73. }
  74. public _update(): void {
  75. for (var renderPassName in this._renderPasses) {
  76. this._renderPasses[renderPassName]._update();
  77. }
  78. }
  79. public addPass(renderPass: PostProcessRenderPass): void {
  80. this._renderPasses[renderPass._name] = renderPass;
  81. this._linkParameters();
  82. }
  83. public removePass(renderPass: PostProcessRenderPass): void {
  84. delete this._renderPasses[renderPass._name];
  85. this._linkParameters();
  86. }
  87. public addRenderEffectAsPass(renderEffect: PostProcessRenderEffect): void {
  88. this._renderEffectAsPasses[renderEffect._name] = renderEffect;
  89. this._linkParameters();
  90. }
  91. public getPass(passName: string): void {
  92. for (var renderPassName in this._renderPasses) {
  93. if (renderPassName === passName) {
  94. return this._renderPasses[passName];
  95. }
  96. }
  97. }
  98. public emptyPasses(): void {
  99. this._renderPasses.length = 0;
  100. this._linkParameters();
  101. }
  102. // private
  103. public _attachCameras(cameras: Camera);
  104. public _attachCameras(cameras: Camera[]);
  105. public _attachCameras(cameras: any): void {
  106. var cameraKey;
  107. var _cam = Tools.MakeArray(cameras || this._cameras);
  108. for (var i = 0; i < _cam.length; i++) {
  109. var camera = _cam[i];
  110. var cameraName = camera.name;
  111. if (this._singleInstance) {
  112. cameraKey = 0;
  113. }
  114. else {
  115. cameraKey = cameraName;
  116. }
  117. this._postProcesses[cameraKey] = this._postProcesses[cameraKey] || PostProcessRenderEffect._GetInstance(this._engine, this._postProcessType, this._ratio, this._samplingMode);
  118. var index = camera.attachPostProcess(this._postProcesses[cameraKey]);
  119. if (this._indicesForCamera[cameraName] === null) {
  120. this._indicesForCamera[cameraName] = [];
  121. }
  122. this._indicesForCamera[cameraName].push(index);
  123. if (this._cameras.indexOf(camera) === -1) {
  124. this._cameras[cameraName] = camera;
  125. }
  126. for (var passName in this._renderPasses) {
  127. this._renderPasses[passName]._incRefCount();
  128. }
  129. }
  130. this._linkParameters();
  131. }
  132. // private
  133. public _detachCameras(cameras: Camera);
  134. public _detachCameras(cameras: Camera[]);
  135. public _detachCameras(cameras: any): void {
  136. var _cam = Tools.MakeArray(cameras || this._cameras);
  137. for (var i = 0; i < _cam.length; i++) {
  138. var camera = _cam[i];
  139. var cameraName = camera.name;
  140. camera.detachPostProcess(this._postProcesses[this._singleInstance ? 0 : cameraName], this._indicesForCamera[cameraName]);
  141. var index = this._cameras.indexOf(cameraName);
  142. this._indicesForCamera.splice(index, 1);
  143. this._cameras.splice(index, 1);
  144. for (var passName in this._renderPasses) {
  145. this._renderPasses[passName]._decRefCount();
  146. }
  147. }
  148. }
  149. // private
  150. public _enable(cameras: Camera);
  151. public _enable(cameras: Camera[]);
  152. public _enable(cameras: any): void {
  153. var _cam = Tools.MakeArray(cameras || this._cameras);
  154. for (var i = 0; i < _cam.length; i++) {
  155. var camera = _cam[i];
  156. var cameraName = camera.name;
  157. for (var j = 0; j < this._indicesForCamera[cameraName].length; j++) {
  158. if (camera._postProcesses[this._indicesForCamera[cameraName][j]] === undefined) {
  159. cameras[i].attachPostProcess(this._postProcesses[this._singleInstance ? 0 : cameraName], this._indicesForCamera[cameraName][j]);
  160. }
  161. }
  162. for (var passName in this._renderPasses) {
  163. this._renderPasses[passName]._incRefCount();
  164. }
  165. }
  166. }
  167. // private
  168. public _disable(cameras: Camera);
  169. public _disable(cameras: Camera[]);
  170. public _disable(cameras: any): void {
  171. var _cam = Tools.MakeArray(cameras || this._cameras);
  172. for (var i = 0; i < _cam.length; i++) {
  173. var camera = _cam[i];
  174. var cameraName = camera.Name;
  175. camera.detachPostProcess(this._postProcesses[this._singleInstance ? 0 : cameraName], this._indicesForCamera[cameraName]);
  176. for (var passName in this._renderPasses) {
  177. this._renderPasses[passName]._decRefCount();
  178. }
  179. }
  180. }
  181. public getPostProcess(camera?: Camera): PostProcess {
  182. if (this._singleInstance) {
  183. return this._postProcesses[0];
  184. }
  185. else {
  186. return this._postProcesses[camera.name];
  187. }
  188. }
  189. private _linkParameters(): void {
  190. for (var index in this._postProcesses) {
  191. this._postProcesses[index].onApply = (effect: Effect) => {
  192. this.parameters(effect);
  193. this._linkTextures(effect);
  194. };
  195. }
  196. }
  197. private _linkTextures(effect): void {
  198. for (var renderPassName in this._renderPasses) {
  199. effect.setTexture(renderPassName, this._renderPasses[renderPassName].getRenderTexture());
  200. }
  201. for (var renderEffectName in this._renderEffectAsPasses) {
  202. effect.setTextureFromPostProcess(renderEffectName + "Sampler", this._renderEffectAsPasses[renderEffectName].getPostProcess());
  203. }
  204. }
  205. }
  206. }