babylon.mirrorTexture.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. module BABYLON {
  2. export class MirrorTexture extends RenderTargetTexture {
  3. public mirrorPlane = new Plane(0, 1, 0, 1);
  4. private _transformMatrix = Matrix.Zero();
  5. private _mirrorMatrix = Matrix.Zero();
  6. private _savedViewMatrix: Matrix;
  7. private _blurX: Nullable<BlurPostProcess>;
  8. private _blurY: Nullable<BlurPostProcess>;
  9. private _adaptiveBlurKernel = 0;
  10. private _blurKernelX = 0;
  11. private _blurKernelY = 0;
  12. private _blurRatio = 1.0;
  13. public set blurRatio(value: number) {
  14. if (this._blurRatio === value) {
  15. return;
  16. }
  17. this._blurRatio = value;
  18. this._preparePostProcesses();
  19. }
  20. public get blurRatio(): number {
  21. return this._blurRatio;
  22. }
  23. public set adaptiveBlurKernel(value: number) {
  24. this._adaptiveBlurKernel = value;
  25. this._autoComputeBlurKernel();
  26. }
  27. public set blurKernel(value: number) {
  28. this.blurKernelX = value;
  29. this.blurKernelY = value;
  30. }
  31. public set blurKernelX(value: number) {
  32. if (this._blurKernelX === value) {
  33. return;
  34. }
  35. this._blurKernelX = value;
  36. this._preparePostProcesses();
  37. }
  38. public get blurKernelX(): number {
  39. return this._blurKernelX;
  40. }
  41. public set blurKernelY(value: number) {
  42. if (this._blurKernelY === value) {
  43. return;
  44. }
  45. this._blurKernelY = value;
  46. this._preparePostProcesses();
  47. }
  48. public get blurKernelY(): number {
  49. return this._blurKernelY;
  50. }
  51. private _autoComputeBlurKernel(): void {
  52. let engine = this.getScene()!.getEngine();
  53. let dw = this.getRenderWidth() / engine.getRenderWidth();
  54. let dh = this.getRenderHeight() / engine.getRenderHeight();
  55. this.blurKernelX = this._adaptiveBlurKernel * dw;
  56. this.blurKernelY = this._adaptiveBlurKernel * dh;
  57. }
  58. protected _onRatioRescale(): void {
  59. if (this._sizeRatio) {
  60. this.resize(this._initialSizeParameter);
  61. if (!this._adaptiveBlurKernel) {
  62. this._preparePostProcesses();
  63. }
  64. }
  65. if (this._adaptiveBlurKernel) {
  66. this._autoComputeBlurKernel();
  67. }
  68. }
  69. private _updateGammaSpace(){
  70. this.gammaSpace = !this.scene.imageProcessingConfiguration.isEnabled || !this.scene.imageProcessingConfiguration.applyByPostProcess;
  71. }
  72. private _imageProcessingConfigChangeObserver:Nullable<Observer<ImageProcessingConfiguration>>;
  73. constructor(name: string, size: number | { width: number, height: number } | { ratio: number }, private scene: Scene, generateMipMaps?: boolean, type: number = Engine.TEXTURETYPE_UNSIGNED_INT, samplingMode = Texture.BILINEAR_SAMPLINGMODE, generateDepthBuffer = true) {
  74. super(name, size, scene, generateMipMaps, true, type, false, samplingMode, generateDepthBuffer);
  75. this.ignoreCameraViewport = true;
  76. this._updateGammaSpace();
  77. this._imageProcessingConfigChangeObserver = scene.imageProcessingConfiguration.onUpdateParameters.add(this._updateGammaSpace)
  78. this.onBeforeRenderObservable.add(() => {
  79. Matrix.ReflectionToRef(this.mirrorPlane, this._mirrorMatrix);
  80. this._savedViewMatrix = scene.getViewMatrix();
  81. this._mirrorMatrix.multiplyToRef(this._savedViewMatrix, this._transformMatrix);
  82. scene.setTransformMatrix(this._transformMatrix, scene.getProjectionMatrix());
  83. scene.clipPlane = this.mirrorPlane;
  84. scene.getEngine().cullBackFaces = false;
  85. scene._mirroredCameraPosition = Vector3.TransformCoordinates((<Camera>scene.activeCamera).globalPosition, this._mirrorMatrix);
  86. });
  87. this.onAfterRenderObservable.add(() => {
  88. scene.setTransformMatrix(this._savedViewMatrix, scene.getProjectionMatrix());
  89. scene.getEngine().cullBackFaces = true;
  90. scene._mirroredCameraPosition = null;
  91. delete scene.clipPlane;
  92. });
  93. }
  94. private _preparePostProcesses(): void {
  95. this.clearPostProcesses(true);
  96. if (this._blurKernelX && this._blurKernelY) {
  97. var engine = (<Scene>this.getScene()).getEngine();
  98. var textureType = engine.getCaps().textureFloatRender ? Engine.TEXTURETYPE_FLOAT : Engine.TEXTURETYPE_HALF_FLOAT;
  99. this._blurX = new BlurPostProcess("horizontal blur", new Vector2(1.0, 0), this._blurKernelX, this._blurRatio, null, Texture.BILINEAR_SAMPLINGMODE, engine, false, textureType);
  100. this._blurX.autoClear = false;
  101. if (this._blurRatio === 1 && this.samples < 2 && this._texture) {
  102. this._blurX.inputTexture = this._texture;
  103. } else {
  104. this._blurX.alwaysForcePOT = true;
  105. }
  106. this._blurY = new BlurPostProcess("vertical blur", new Vector2(0, 1.0), this._blurKernelY, this._blurRatio, null, Texture.BILINEAR_SAMPLINGMODE, engine, false, textureType);
  107. this._blurY.autoClear = false;
  108. this._blurY.alwaysForcePOT = this._blurRatio !== 1;
  109. this.addPostProcess(this._blurX);
  110. this.addPostProcess(this._blurY);
  111. }
  112. else {
  113. if (this._blurY) {
  114. this.removePostProcess(this._blurY);
  115. this._blurY.dispose();
  116. this._blurY = null;
  117. }
  118. if (this._blurX) {
  119. this.removePostProcess(this._blurX);
  120. this._blurX.dispose();
  121. this._blurX = null;
  122. }
  123. }
  124. }
  125. public clone(): MirrorTexture {
  126. let scene = this.getScene();
  127. if (!scene) {
  128. return this;
  129. }
  130. var textureSize = this.getSize();
  131. var newTexture = new MirrorTexture(
  132. this.name,
  133. textureSize.width,
  134. scene,
  135. this._renderTargetOptions.generateMipMaps,
  136. this._renderTargetOptions.type,
  137. this._renderTargetOptions.samplingMode,
  138. this._renderTargetOptions.generateDepthBuffer
  139. );
  140. // Base texture
  141. newTexture.hasAlpha = this.hasAlpha;
  142. newTexture.level = this.level;
  143. // Mirror Texture
  144. newTexture.mirrorPlane = this.mirrorPlane.clone();
  145. if (this.renderList) {
  146. newTexture.renderList = this.renderList.slice(0);
  147. }
  148. return newTexture;
  149. }
  150. public serialize(): any {
  151. if (!this.name) {
  152. return null;
  153. }
  154. var serializationObject = super.serialize();
  155. serializationObject.mirrorPlane = this.mirrorPlane.asArray();
  156. return serializationObject;
  157. }
  158. public dispose(){
  159. super.dispose();
  160. this.scene.imageProcessingConfiguration.onUpdateParameters.remove(this._imageProcessingConfigChangeObserver);
  161. }
  162. }
  163. }