babylon.renderTargetTexture.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. module BABYLON {
  2. export class RenderTargetTexture extends Texture {
  3. public static _REFRESHRATE_RENDER_ONCE: number = 0;
  4. public static _REFRESHRATE_RENDER_ONEVERYFRAME: number = 1;
  5. public static _REFRESHRATE_RENDER_ONEVERYTWOFRAMES: number = 2;
  6. public static get REFRESHRATE_RENDER_ONCE(): number {
  7. return RenderTargetTexture._REFRESHRATE_RENDER_ONCE;
  8. }
  9. public static get REFRESHRATE_RENDER_ONEVERYFRAME(): number {
  10. return RenderTargetTexture._REFRESHRATE_RENDER_ONEVERYFRAME;
  11. }
  12. public static get REFRESHRATE_RENDER_ONEVERYTWOFRAMES(): number {
  13. return RenderTargetTexture._REFRESHRATE_RENDER_ONEVERYTWOFRAMES;
  14. }
  15. public renderList = new Array<AbstractMesh>();
  16. public renderParticles = true;
  17. public renderSprites = false;
  18. public coordinatesMode = Texture.PROJECTION_MODE;
  19. public onBeforeRender: (faceIndex: number) => void;
  20. public onAfterRender: (faceIndex: number) => void;
  21. public onAfterUnbind: () => void;
  22. public onClear: (engine: Engine) => void;
  23. public activeCamera: Camera;
  24. public customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents?: () => void) => void;
  25. private _size: number;
  26. public _generateMipMaps: boolean;
  27. private _renderingManager: RenderingManager;
  28. public _waitingRenderList: string[];
  29. private _doNotChangeAspectRatio: boolean;
  30. private _currentRefreshId = -1;
  31. private _refreshRate = 1;
  32. private _textureMatrix: Matrix;
  33. constructor(name: string, size: any, scene: Scene, generateMipMaps?: boolean, doNotChangeAspectRatio: boolean = true, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, public isCube = false) {
  34. super(null, scene, !generateMipMaps);
  35. this.name = name;
  36. this.isRenderTarget = true;
  37. this._size = size;
  38. this._generateMipMaps = generateMipMaps;
  39. this._doNotChangeAspectRatio = doNotChangeAspectRatio;
  40. if (isCube) {
  41. this._texture = scene.getEngine().createRenderTargetCubeTexture(size, { generateMipMaps: generateMipMaps });
  42. this.coordinatesMode = Texture.INVCUBIC_MODE;
  43. this._textureMatrix = Matrix.Identity();
  44. } else {
  45. this._texture = scene.getEngine().createRenderTargetTexture(size, { generateMipMaps: generateMipMaps, type: type });
  46. }
  47. // Rendering groups
  48. this._renderingManager = new RenderingManager(scene);
  49. }
  50. public resetRefreshCounter(): void {
  51. this._currentRefreshId = -1;
  52. }
  53. public get refreshRate(): number {
  54. return this._refreshRate;
  55. }
  56. // Use 0 to render just once, 1 to render on every frame, 2 to render every two frames and so on...
  57. public set refreshRate(value: number) {
  58. this._refreshRate = value;
  59. this.resetRefreshCounter();
  60. }
  61. public _shouldRender(): boolean {
  62. if (this._currentRefreshId === -1) { // At least render once
  63. this._currentRefreshId = 1;
  64. return true;
  65. }
  66. if (this.refreshRate === this._currentRefreshId) {
  67. this._currentRefreshId = 1;
  68. return true;
  69. }
  70. this._currentRefreshId++;
  71. return false;
  72. }
  73. public isReady(): boolean {
  74. if (!this.getScene().renderTargetsEnabled) {
  75. return false;
  76. }
  77. return super.isReady();
  78. }
  79. public getRenderSize(): number {
  80. return this._size;
  81. }
  82. public get canRescale(): boolean {
  83. return true;
  84. }
  85. public scale(ratio: number): void {
  86. var newSize = this._size * ratio;
  87. this.resize(newSize, this._generateMipMaps);
  88. }
  89. public getReflectionTextureMatrix(): Matrix {
  90. if (this.isCube) {
  91. return this._textureMatrix;
  92. }
  93. return super.getReflectionTextureMatrix();
  94. }
  95. public resize(size: any, generateMipMaps?: boolean) {
  96. this.releaseInternalTexture();
  97. if (this.isCube) {
  98. this._texture = this.getScene().getEngine().createRenderTargetCubeTexture(size);
  99. } else {
  100. this._texture = this.getScene().getEngine().createRenderTargetTexture(size, generateMipMaps);
  101. }
  102. }
  103. public render(useCameraPostProcess?: boolean, dumpForDebug?: boolean) {
  104. var scene = this.getScene();
  105. if (this.activeCamera && this.activeCamera !== scene.activeCamera) {
  106. scene.setTransformMatrix(this.activeCamera.getViewMatrix(), this.activeCamera.getProjectionMatrix(true));
  107. }
  108. if (this._waitingRenderList) {
  109. this.renderList = [];
  110. for (var index = 0; index < this._waitingRenderList.length; index++) {
  111. var id = this._waitingRenderList[index];
  112. this.renderList.push(scene.getMeshByID(id));
  113. }
  114. delete this._waitingRenderList;
  115. }
  116. if (this.renderList && this.renderList.length === 0) {
  117. return;
  118. }
  119. // Prepare renderingManager
  120. this._renderingManager.reset();
  121. var currentRenderList = this.renderList ? this.renderList : scene.getActiveMeshes().data;
  122. for (var meshIndex = 0; meshIndex < currentRenderList.length; meshIndex++) {
  123. var mesh = currentRenderList[meshIndex];
  124. if (mesh) {
  125. if (!mesh.isReady()) {
  126. // Reset _currentRefreshId
  127. this.resetRefreshCounter();
  128. continue;
  129. }
  130. if (mesh.isEnabled() && mesh.isVisible && mesh.subMeshes && ((mesh.layerMask & scene.activeCamera.layerMask) !== 0)) {
  131. mesh._activate(scene.getRenderId());
  132. for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
  133. var subMesh = mesh.subMeshes[subIndex];
  134. scene._activeIndices += subMesh.indexCount;
  135. this._renderingManager.dispatch(subMesh);
  136. }
  137. }
  138. }
  139. }
  140. if (this.isCube) {
  141. for (var face = 0; face < 6; face++) {
  142. this.renderToTarget(face, currentRenderList, useCameraPostProcess, dumpForDebug);
  143. scene.incrementRenderId();
  144. }
  145. } else {
  146. this.renderToTarget(0, currentRenderList, useCameraPostProcess, dumpForDebug);
  147. }
  148. if (this.onAfterUnbind) {
  149. this.onAfterUnbind();
  150. }
  151. if (this.activeCamera && this.activeCamera !== scene.activeCamera) {
  152. scene.setTransformMatrix(scene.activeCamera.getViewMatrix(), scene.activeCamera.getProjectionMatrix(true));
  153. }
  154. scene.resetCachedMaterial();
  155. }
  156. renderToTarget(faceIndex: number, currentRenderList: AbstractMesh[], useCameraPostProcess: boolean, dumpForDebug: boolean): void {
  157. var scene = this.getScene();
  158. var engine = scene.getEngine();
  159. // Bind
  160. if (!useCameraPostProcess || !scene.postProcessManager._prepareFrame(this._texture)) {
  161. if (this.isCube) {
  162. engine.bindFramebuffer(this._texture, faceIndex);
  163. } else {
  164. engine.bindFramebuffer(this._texture);
  165. }
  166. }
  167. if (this.onBeforeRender) {
  168. this.onBeforeRender(faceIndex);
  169. }
  170. // Clear
  171. if (this.onClear) {
  172. this.onClear(engine);
  173. } else {
  174. engine.clear(scene.clearColor, true, true);
  175. }
  176. if (!this._doNotChangeAspectRatio) {
  177. scene.updateTransformMatrix(true);
  178. }
  179. // Render
  180. this._renderingManager.render(this.customRenderFunction, currentRenderList, this.renderParticles, this.renderSprites);
  181. if (useCameraPostProcess) {
  182. scene.postProcessManager._finalizeFrame(false, this._texture, faceIndex);
  183. }
  184. if (!this._doNotChangeAspectRatio) {
  185. scene.updateTransformMatrix(true);
  186. }
  187. if (this.onAfterRender) {
  188. this.onAfterRender(faceIndex);
  189. }
  190. // Dump ?
  191. if (dumpForDebug) {
  192. Tools.DumpFramebuffer(this._size, this._size, engine);
  193. }
  194. // Unbind
  195. if (!this.isCube || faceIndex === 5) {
  196. if (this.isCube) {
  197. if (faceIndex === 5) {
  198. engine.generateMipMapsForCubemap(this._texture);
  199. }
  200. }
  201. engine.unBindFramebuffer(this._texture, this.isCube);
  202. }
  203. }
  204. public clone(): RenderTargetTexture {
  205. var textureSize = this.getSize();
  206. var newTexture = new RenderTargetTexture(this.name, textureSize.width, this.getScene(), this._generateMipMaps);
  207. // Base texture
  208. newTexture.hasAlpha = this.hasAlpha;
  209. newTexture.level = this.level;
  210. // RenderTarget Texture
  211. newTexture.coordinatesMode = this.coordinatesMode;
  212. newTexture.renderList = this.renderList.slice(0);
  213. return newTexture;
  214. }
  215. public serialize(): any {
  216. if (!this.name) {
  217. return null;
  218. }
  219. var serializationObject = super.serialize();
  220. serializationObject.renderTargetSize = this.getRenderSize();
  221. serializationObject.renderList = [];
  222. for (var index = 0; index < this.renderList.length; index++) {
  223. serializationObject.renderList.push(this.renderList[index].id);
  224. }
  225. return serializationObject;
  226. }
  227. }
  228. }