screenshotTools.ts 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. import { Nullable } from "../types";
  2. import { Camera } from "../Cameras/camera";
  3. import { Texture } from "../Materials/Textures/texture";
  4. import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
  5. import { FxaaPostProcess } from "../PostProcesses/fxaaPostProcess";
  6. import { Constants } from "../Engines/constants";
  7. import { Logger } from "./logger";
  8. import { _TypeStore } from "./typeStore";
  9. import { Tools } from './tools';
  10. declare type Engine = import("../Engines/engine").Engine;
  11. /**
  12. * Class containing a set of static utilities functions for screenshots
  13. */
  14. export class ScreenshotTools {
  15. /**
  16. * Captures a screenshot of the current rendering
  17. * @see http://doc.babylonjs.com/how_to/render_scene_on_a_png
  18. * @param engine defines the rendering engine
  19. * @param camera defines the source camera
  20. * @param size This parameter can be set to a single number or to an object with the
  21. * following (optional) properties: precision, width, height. If a single number is passed,
  22. * it will be used for both width and height. If an object is passed, the screenshot size
  23. * will be derived from the parameters. The precision property is a multiplier allowing
  24. * rendering at a higher or lower resolution
  25. * @param successCallback defines the callback receives a single parameter which contains the
  26. * screenshot as a string of base64-encoded characters. This string can be assigned to the
  27. * src parameter of an <img> to display it
  28. * @param mimeType defines the MIME type of the screenshot image (default: image/png).
  29. * Check your browser for supported MIME types
  30. */
  31. public static CreateScreenshot(engine: Engine, camera: Camera, size: any, successCallback?: (data: string) => void, mimeType: string = "image/png"): void {
  32. var width: number;
  33. var height: number;
  34. // If a precision value is specified
  35. if (size.precision) {
  36. width = Math.round(engine.getRenderWidth() * size.precision);
  37. height = Math.round(width / engine.getAspectRatio(camera));
  38. }
  39. else if (size.width && size.height) {
  40. width = size.width;
  41. height = size.height;
  42. }
  43. //If passing only width, computing height to keep display canvas ratio.
  44. else if (size.width && !size.height) {
  45. width = size.width;
  46. height = Math.round(width / engine.getAspectRatio(camera));
  47. }
  48. //If passing only height, computing width to keep display canvas ratio.
  49. else if (size.height && !size.width) {
  50. height = size.height;
  51. width = Math.round(height * engine.getAspectRatio(camera));
  52. }
  53. //Assuming here that "size" parameter is a number
  54. else if (!isNaN(size)) {
  55. height = size;
  56. width = size;
  57. }
  58. else {
  59. Logger.Error("Invalid 'size' parameter !");
  60. return;
  61. }
  62. if (!Tools._ScreenshotCanvas) {
  63. Tools._ScreenshotCanvas = document.createElement('canvas');
  64. }
  65. Tools._ScreenshotCanvas.width = width;
  66. Tools._ScreenshotCanvas.height = height;
  67. var renderContext = Tools._ScreenshotCanvas.getContext("2d");
  68. var ratio = engine.getRenderWidth() / engine.getRenderHeight();
  69. var newWidth = width;
  70. var newHeight = newWidth / ratio;
  71. if (newHeight > height) {
  72. newHeight = height;
  73. newWidth = newHeight * ratio;
  74. }
  75. var offsetX = Math.max(0, width - newWidth) / 2;
  76. var offsetY = Math.max(0, height - newHeight) / 2;
  77. var renderingCanvas = engine.getRenderingCanvas();
  78. if (renderContext && renderingCanvas) {
  79. renderContext.drawImage(renderingCanvas, offsetX, offsetY, newWidth, newHeight);
  80. }
  81. Tools.EncodeScreenshotCanvasData(successCallback, mimeType);
  82. }
  83. /**
  84. * Generates an image screenshot from the specified camera.
  85. * @see http://doc.babylonjs.com/how_to/render_scene_on_a_png
  86. * @param engine The engine to use for rendering
  87. * @param camera The camera to use for rendering
  88. * @param size This parameter can be set to a single number or to an object with the
  89. * following (optional) properties: precision, width, height. If a single number is passed,
  90. * it will be used for both width and height. If an object is passed, the screenshot size
  91. * will be derived from the parameters. The precision property is a multiplier allowing
  92. * rendering at a higher or lower resolution
  93. * @param successCallback The callback receives a single parameter which contains the
  94. * screenshot as a string of base64-encoded characters. This string can be assigned to the
  95. * src parameter of an <img> to display it
  96. * @param mimeType The MIME type of the screenshot image (default: image/png).
  97. * Check your browser for supported MIME types
  98. * @param samples Texture samples (default: 1)
  99. * @param antialiasing Whether antialiasing should be turned on or not (default: false)
  100. * @param fileName A name for for the downloaded file.
  101. */
  102. public static CreateScreenshotUsingRenderTarget(engine: Engine, camera: Camera, size: any, successCallback?: (data: string) => void, mimeType: string = "image/png", samples: number = 1, antialiasing: boolean = false, fileName?: string): void {
  103. var width: number;
  104. var height: number;
  105. //If a precision value is specified
  106. if (size.precision) {
  107. width = Math.round(engine.getRenderWidth() * size.precision);
  108. height = Math.round(width / engine.getAspectRatio(camera));
  109. size = { width: width, height: height };
  110. }
  111. else if (size.width && size.height) {
  112. width = size.width;
  113. height = size.height;
  114. }
  115. //If passing only width, computing height to keep display canvas ratio.
  116. else if (size.width && !size.height) {
  117. width = size.width;
  118. height = Math.round(width / engine.getAspectRatio(camera));
  119. size = { width: width, height: height };
  120. }
  121. //If passing only height, computing width to keep display canvas ratio.
  122. else if (size.height && !size.width) {
  123. height = size.height;
  124. width = Math.round(height * engine.getAspectRatio(camera));
  125. size = { width: width, height: height };
  126. }
  127. //Assuming here that "size" parameter is a number
  128. else if (!isNaN(size)) {
  129. height = size;
  130. width = size;
  131. }
  132. else {
  133. Logger.Error("Invalid 'size' parameter !");
  134. return;
  135. }
  136. var scene = camera.getScene();
  137. var previousCamera: Nullable<Camera> = null;
  138. if (scene.activeCamera !== camera) {
  139. previousCamera = scene.activeCamera;
  140. scene.activeCamera = camera;
  141. }
  142. var renderCanvas = engine.getRenderingCanvas();
  143. if (!renderCanvas) {
  144. Logger.Error("No rendering canvas found !");
  145. return;
  146. }
  147. var originalSize = { width: renderCanvas.width, height: renderCanvas.height };
  148. engine.setSize(width, height);
  149. scene.render();
  150. // At this point size can be a number, or an object (according to engine.prototype.createRenderTargetTexture method)
  151. var texture = new RenderTargetTexture("screenShot", size, scene, false, false, Constants.TEXTURETYPE_UNSIGNED_INT, false, Texture.NEAREST_SAMPLINGMODE);
  152. texture.renderList = null;
  153. texture.samples = samples;
  154. if (antialiasing) {
  155. texture.addPostProcess(new FxaaPostProcess('antialiasing', 1.0, scene.activeCamera));
  156. }
  157. texture.onAfterRenderObservable.add(() => {
  158. Tools.DumpFramebuffer(width, height, engine, successCallback, mimeType, fileName);
  159. });
  160. scene.incrementRenderId();
  161. scene.resetCachedMaterial();
  162. texture.render(true);
  163. texture.dispose();
  164. if (previousCamera) {
  165. scene.activeCamera = previousCamera;
  166. }
  167. engine.setSize(originalSize.width, originalSize.height);
  168. camera.getProjectionMatrix(true); // Force cache refresh;
  169. }
  170. }
  171. Tools.CreateScreenshot = ScreenshotTools.CreateScreenshot;
  172. Tools.CreateScreenshotUsingRenderTarget = ScreenshotTools.CreateScreenshotUsingRenderTarget;