prePassRendererSceneComponent.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import { Nullable } from "../types";
  2. import { Scene } from "../scene";
  3. import { ISceneComponent, SceneComponentConstants } from "../sceneComponent";
  4. import { PrePassRenderer } from "./prePassRenderer";
  5. import { Logger } from "../Misc/logger";
  6. import { AbstractMesh } from "../Meshes/abstractMesh";
  7. import { SubMesh } from "../Meshes/subMesh";
  8. import { _InstancesBatch } from "../Meshes/mesh";
  9. import { Effect } from "../Materials/effect";
  10. import { Camera } from '../Cameras/camera';
  11. import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
  12. import { PrePassRenderTarget } from "../Materials/Textures/prePassRenderTarget";
  13. declare module "../abstractScene" {
  14. export interface AbstractScene {
  15. /** @hidden (Backing field) */
  16. _prePassRenderer: Nullable<PrePassRenderer>;
  17. /**
  18. * Gets or Sets the current prepass renderer associated to the scene.
  19. */
  20. prePassRenderer: Nullable<PrePassRenderer>;
  21. /**
  22. * Enables the prepass and associates it with the scene
  23. * @returns the PrePassRenderer
  24. */
  25. enablePrePassRenderer(): Nullable<PrePassRenderer>;
  26. /**
  27. * Disables the prepass associated with the scene
  28. */
  29. disablePrePassRenderer(): void;
  30. }
  31. }
  32. declare module "../Materials/Textures/renderTargetTexture" {
  33. export interface RenderTargetTexture {
  34. /** @hidden */
  35. _prePassRenderTarget: PrePassRenderTarget;
  36. }
  37. }
  38. Object.defineProperty(Scene.prototype, "prePassRenderer", {
  39. get: function(this: Scene) {
  40. return this._prePassRenderer;
  41. },
  42. set: function(this: Scene, value: Nullable<PrePassRenderer>) {
  43. if (value && value.isSupported) {
  44. this._prePassRenderer = value;
  45. }
  46. },
  47. enumerable: true,
  48. configurable: true
  49. });
  50. Scene.prototype.enablePrePassRenderer = function(): Nullable<PrePassRenderer> {
  51. if (this._prePassRenderer) {
  52. return this._prePassRenderer;
  53. }
  54. this._prePassRenderer = new PrePassRenderer(this);
  55. if (!this._prePassRenderer.isSupported) {
  56. this._prePassRenderer = null;
  57. Logger.Error("PrePassRenderer needs WebGL 2 support.\n" +
  58. "Maybe you tried to use the following features that need the PrePassRenderer :\n" +
  59. " + Subsurface Scattering");
  60. }
  61. return this._prePassRenderer;
  62. };
  63. Scene.prototype.disablePrePassRenderer = function(): void {
  64. if (!this._prePassRenderer) {
  65. return;
  66. }
  67. this._prePassRenderer.dispose();
  68. this._prePassRenderer = null;
  69. };
  70. /**
  71. * Defines the Geometry Buffer scene component responsible to manage a G-Buffer useful
  72. * in several rendering techniques.
  73. */
  74. export class PrePassRendererSceneComponent implements ISceneComponent {
  75. /**
  76. * The component name helpful to identify the component in the list of scene components.
  77. */
  78. public readonly name = SceneComponentConstants.NAME_PREPASSRENDERER;
  79. /**
  80. * The scene the component belongs to.
  81. */
  82. public scene: Scene;
  83. /**
  84. * Creates a new instance of the component for the given scene
  85. * @param scene Defines the scene to register the component in
  86. */
  87. constructor(scene: Scene) {
  88. this.scene = scene;
  89. }
  90. /**
  91. * Registers the component in a given scene
  92. */
  93. public register(): void {
  94. this.scene._beforeCameraDrawStage.registerStep(SceneComponentConstants.STEP_BEFORECAMERADRAW_PREPASS, this, this._beforeCameraDraw);
  95. this.scene._afterCameraDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this._afterCameraDraw);
  96. this.scene._beforeRenderTargetDrawStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERTARGETDRAW_PREPASS, this, this._beforeRenderTargetDraw);
  97. this.scene._afterRenderTargetDrawStage.registerStep(SceneComponentConstants.STEP_AFTERCAMERADRAW_PREPASS, this, this._afterRenderTargetDraw);
  98. this.scene._beforeClearStage.registerStep(SceneComponentConstants.STEP_BEFORECLEARSTAGE_PREPASS, this, this._beforeClearStage);
  99. this.scene._beforeRenderTargetClearStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERTARGETCLEARSTAGE_PREPASS, this, this._beforeRenderTargetClearStage);
  100. this.scene._beforeRenderingMeshStage.registerStep(SceneComponentConstants.STEP_BEFORERENDERINGMESH_PREPASS, this, this._beforeRenderingMeshStage);
  101. this.scene._afterRenderingMeshStage.registerStep(SceneComponentConstants.STEP_AFTERRENDERINGMESH_PREPASS, this, this._afterRenderingMeshStage);
  102. }
  103. private _beforeRenderTargetDraw(renderTarget: RenderTargetTexture, faceIndex?: number, layer?: number) {
  104. if (this.scene.prePassRenderer) {
  105. if (!renderTarget._prePassRenderTarget) {
  106. renderTarget._prePassRenderTarget = this.scene.prePassRenderer._createRenderTarget(renderTarget.name + "_prePassRTT", renderTarget);
  107. }
  108. this.scene.prePassRenderer._setRenderTarget(renderTarget._prePassRenderTarget);
  109. this.scene.prePassRenderer._beforeDraw(undefined, faceIndex, layer);
  110. }
  111. }
  112. private _afterRenderTargetDraw(renderTarget: RenderTargetTexture, faceIndex?: number, layer?: number) {
  113. if (this.scene.prePassRenderer) {
  114. this.scene.prePassRenderer._afterDraw(faceIndex, layer);
  115. }
  116. }
  117. private _beforeRenderTargetClearStage(renderTarget: RenderTargetTexture, faceIndex?: number, layer?: number) {
  118. if (this.scene.prePassRenderer) {
  119. this.scene.prePassRenderer._setRenderTarget(renderTarget._prePassRenderTarget);
  120. this.scene.prePassRenderer._clear();
  121. }
  122. }
  123. private _beforeCameraDraw(camera: Camera) {
  124. if (this.scene.prePassRenderer) {
  125. this.scene.prePassRenderer._setRenderTarget(null);
  126. this.scene.prePassRenderer._beforeDraw(camera);
  127. }
  128. }
  129. private _afterCameraDraw(camera: Camera) {
  130. if (this.scene.prePassRenderer) {
  131. this.scene.prePassRenderer._afterDraw();
  132. }
  133. }
  134. private _beforeClearStage() {
  135. if (this.scene.prePassRenderer) {
  136. this.scene.prePassRenderer._setRenderTarget(null);
  137. this.scene.prePassRenderer._clear();
  138. }
  139. }
  140. private _beforeRenderingMeshStage(mesh: AbstractMesh, subMesh: SubMesh, batch: _InstancesBatch, effect: Nullable<Effect>) {
  141. if (!effect) {
  142. return;
  143. }
  144. // Render to MRT
  145. const scene = mesh.getScene();
  146. if (scene.prePassRenderer) {
  147. scene.prePassRenderer.bindAttachmentsForEffect(effect, subMesh);
  148. }
  149. }
  150. private _afterRenderingMeshStage(mesh: AbstractMesh) {
  151. const scene = mesh.getScene();
  152. if (scene.prePassRenderer) {
  153. scene.prePassRenderer.restoreAttachments();
  154. }
  155. }
  156. /**
  157. * Rebuilds the elements related to this component in case of
  158. * context lost for instance.
  159. */
  160. public rebuild(): void {
  161. // Release textures first
  162. this.scene.disablePrePassRenderer();
  163. // Re-enable
  164. this.scene.enablePrePassRenderer();
  165. }
  166. /**
  167. * Disposes the component and the associated ressources
  168. */
  169. public dispose(): void {
  170. this.scene.disablePrePassRenderer();
  171. }
  172. }
  173. PrePassRenderer._SceneComponentInitialization = (scene: Scene) => {
  174. // Register the G Buffer component to the scene.
  175. let component = scene._getComponent(SceneComponentConstants.NAME_PREPASSRENDERER) as PrePassRendererSceneComponent;
  176. if (!component) {
  177. component = new PrePassRendererSceneComponent(scene);
  178. scene._addComponent(component);
  179. }
  180. };