textureTools.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import { InternalTexture } from "../Materials/Textures/internalTexture";
  2. import { Texture } from "../Materials/Textures/texture";
  3. import { RenderTargetTexture } from "../Materials/Textures/renderTargetTexture";
  4. import { PassPostProcess } from "../PostProcesses/passPostProcess";
  5. import { Constants } from "../Engines/constants";
  6. import { Scene } from "../scene";
  7. import { Nullable } from "../types";
  8. /**
  9. * Class used to host texture specific utilities
  10. */
  11. export class TextureTools {
  12. /**
  13. * Uses the GPU to create a copy texture rescaled at a given size
  14. * @param texture Texture to copy from
  15. * @param width defines the desired width
  16. * @param height defines the desired height
  17. * @param useBilinearMode defines if bilinear mode has to be used
  18. * @return the generated texture
  19. */
  20. public static CreateResizedCopy(texture: Texture, width: number, height: number, useBilinearMode: boolean = true): Texture {
  21. var scene = <Scene>texture.getScene();
  22. var engine = scene.getEngine();
  23. let rtt = new RenderTargetTexture(
  24. 'resized' + texture.name,
  25. { width: width, height: height },
  26. scene,
  27. !texture.noMipmap,
  28. true,
  29. (<InternalTexture>texture._texture).type,
  30. false,
  31. texture.samplingMode,
  32. false
  33. );
  34. rtt.wrapU = texture.wrapU;
  35. rtt.wrapV = texture.wrapV;
  36. rtt.uOffset = texture.uOffset;
  37. rtt.vOffset = texture.vOffset;
  38. rtt.uScale = texture.uScale;
  39. rtt.vScale = texture.vScale;
  40. rtt.uAng = texture.uAng;
  41. rtt.vAng = texture.vAng;
  42. rtt.wAng = texture.wAng;
  43. rtt.coordinatesIndex = texture.coordinatesIndex;
  44. rtt.level = texture.level;
  45. rtt.anisotropicFilteringLevel = texture.anisotropicFilteringLevel;
  46. (<InternalTexture>rtt._texture).isReady = false;
  47. texture.wrapU = Texture.CLAMP_ADDRESSMODE;
  48. texture.wrapV = Texture.CLAMP_ADDRESSMODE;
  49. let passPostProcess = new PassPostProcess("pass", 1, null, useBilinearMode ? Texture.BILINEAR_SAMPLINGMODE : Texture.NEAREST_SAMPLINGMODE, engine, false, Constants.TEXTURETYPE_UNSIGNED_INT);
  50. passPostProcess.getEffect().executeWhenCompiled(() => {
  51. passPostProcess.onApply = function(effect) {
  52. effect.setTexture("textureSampler", texture);
  53. };
  54. let internalTexture = rtt.getInternalTexture();
  55. if (internalTexture) {
  56. scene.postProcessManager.directRender([passPostProcess], internalTexture);
  57. engine.unBindFramebuffer(internalTexture);
  58. rtt.disposeFramebufferObjects();
  59. passPostProcess.dispose();
  60. internalTexture.isReady = true;
  61. }
  62. });
  63. return rtt;
  64. }
  65. /**
  66. * Reads the pixels stored in the webgl texture and returns them as a base64 string
  67. * @param texture defines the texture to read pixels from
  68. * @param faceIndex defines the face of the texture to read (in case of cube texture)
  69. * @param level defines the LOD level of the texture to read (in case of Mip Maps)
  70. * @returns The base64 encoded string or null
  71. */
  72. public static GenerateBase64StringFromTexture(texture: Texture, faceIndex = 0, level = 0): Nullable<string> {
  73. var internalTexture = texture.getInternalTexture();
  74. if (!internalTexture || internalTexture.isCube) {
  75. return null;
  76. }
  77. var pixels = texture.readPixels(faceIndex, level);
  78. if (!pixels) {
  79. return null;
  80. }
  81. var size = texture.getSize();
  82. var width = size.width;
  83. var height = size.height;
  84. if (pixels instanceof Float32Array) {
  85. var len = pixels.byteLength / pixels.BYTES_PER_ELEMENT;
  86. var npixels = new Uint8Array(len);
  87. while (--len >= 0) {
  88. var val = pixels[len];
  89. if (val < 0) {
  90. val = 0;
  91. } else if (val > 1) {
  92. val = 1;
  93. }
  94. npixels[len] = val * 255;
  95. }
  96. pixels = npixels;
  97. }
  98. var canvas = document.createElement('canvas');
  99. canvas.width = width;
  100. canvas.height = height;
  101. var ctx = canvas.getContext('2d');
  102. if (!ctx) {
  103. return null;
  104. }
  105. var imageData = ctx.createImageData(width, height);
  106. imageData.data.set(pixels as ArrayLike<number>);
  107. ctx.putImageData(imageData, 0, 0);
  108. if (internalTexture.invertY) {
  109. var canvas2 = document.createElement('canvas');
  110. canvas2.width = width;
  111. canvas2.height = height;
  112. var ctx2 = canvas2.getContext('2d');
  113. if (!ctx2) {
  114. return null;
  115. }
  116. ctx2.translate(0, height);
  117. ctx2.scale(1, -1);
  118. ctx2.drawImage(canvas, 0, 0);
  119. return canvas2.toDataURL('image/png');
  120. }
  121. return canvas.toDataURL('image/png');
  122. }
  123. }