فهرست منبع

Merge pull request #9168 from aWeirdo/patch-2

Introduce Texture.ForceSerializeBuffers
David Catuhe 4 سال پیش
والد
کامیت
1d60be346c
4فایلهای تغییر یافته به همراه96 افزوده شده و 2 حذف شده
  1. 2 0
      dist/preview release/what's new.md
  2. 10 1
      src/Materials/Textures/texture.ts
  3. 82 0
      src/Misc/copyTools.ts
  4. 2 1
      src/Misc/index.ts

+ 2 - 0
dist/preview release/what's new.md

@@ -56,6 +56,7 @@
 - Add a `disableBoundingBoxesFromEffectLayer` property to the `EffectLayer` class to render the bounding boxes unaffected by the effect ([Popov72](https://github.com/Popov72))
 - Removed all references to HTML element from cameras' attach and detach control functions ([RaananW](https://github.com/RaananW))
 - Added `boundingBoxRenderer.onResourcesReadyObservable` ([aWeirdo](https://github.com/aWeirdo))
+- Added `copyTools.GenerateBase64StringFromTexture` ([aWeirdo](https://github.com/aWeirdo))
 
 ### Engine
 
@@ -244,6 +245,7 @@
 
 - .HDR environment files will now give accurate PBR reflections ([CraigFeldpsar](https://github.com/craigfeldspar))
 - Added a `homogeneousRotationInUVTransform` property in the `Texture` to avoid deformations when rotating the texture with non-uniform scaling ([Popov72](https://github.com/Popov72))
+- Added `Texture.ForceSerializeBuffers` ([aWeirdo](https://github.com/aWeirdo))
 
 ### Audio
 

+ 10 - 1
src/Materials/Textures/texture.ts

@@ -12,6 +12,7 @@ import { TimingTools } from '../../Misc/timingTools';
 import { InstantiationTools } from '../../Misc/instantiationTools';
 import { Plane } from '../../Maths/math.plane';
 import { StringTools } from '../../Misc/stringTools';
+import { CopyTools } from '../../Misc/copyTools';
 
 declare type CubeTexture = import("../../Materials/Textures/cubeTexture").CubeTexture;
 declare type MirrorTexture = import("../../Materials/Textures/mirrorTexture").MirrorTexture;
@@ -28,6 +29,12 @@ export class Texture extends BaseTexture {
      */
     public static SerializeBuffers = true;
 
+    /**
+     * Gets or sets a general boolean used to indicate that texture buffers must be saved as part of the serialization process.
+     * If no buffer exists, one will be created as base64 string from the internal webgl data.
+     */
+    public static ForceSerializeBuffers = false;
+
     /** @hidden */
     public static _CubeTextureParser = (jsonTexture: any, scene: Scene, rootUrl: string): CubeTexture => {
         throw _DevTools.WarnImport("CubeTexture");
@@ -667,12 +674,14 @@ export class Texture extends BaseTexture {
             return null;
         }
 
-        if (Texture.SerializeBuffers) {
+        if (Texture.SerializeBuffers || Texture.ForceSerializeBuffers) {
             if (typeof this._buffer === "string" && (this._buffer as string).substr(0, 5) === "data:") {
                 serializationObject.base64String = this._buffer;
                 serializationObject.name = serializationObject.name.replace("data:", "");
             } else if (this.url && StringTools.StartsWith(this.url, "data:") && this._buffer instanceof Uint8Array) {
                 serializationObject.base64String = "data:image/png;base64," + StringTools.EncodeArrayBufferToBase64(this._buffer);
+            } else if (Texture.ForceSerializeBuffers) {
+                serializationObject.base64String = CopyTools.GenerateBase64StringFromTexture(this);
             }
         }
 

+ 82 - 0
src/Misc/copyTools.ts

@@ -0,0 +1,82 @@
+import { Nullable } from "../types";
+
+declare type BaseTexture = import("../Materials/Textures/baseTexture").BaseTexture;
+
+/**
+ * Class used to host copy specific utilities
+ */
+export class CopyTools {
+    /**
+     * Reads the pixels stored in the webgl texture and returns them as a base64 string
+     * @param texture defines the texture to read pixels from
+     * @param faceIndex defines the face of the texture to read (in case of cube texture)
+     * @param level defines the LOD level of the texture to read (in case of Mip Maps)
+     * @returns The base64 encoded string or null
+     */
+    public static GenerateBase64StringFromTexture(texture: BaseTexture, faceIndex = 0, level = 0): Nullable<string> {
+
+        var internalTexture = texture.getInternalTexture();
+        if (!internalTexture) {
+            return null;
+        }
+
+        var pixels = texture.readPixels(faceIndex, level);
+        if (!pixels) {
+            return null;
+        }
+
+        var size = texture.getSize();
+        var width = size.width;
+        var height = size.height;
+
+        if (pixels instanceof Float32Array) {
+            var len = pixels.byteLength / pixels.BYTES_PER_ELEMENT;
+            var npixels = new Uint8Array(len);
+
+            while (--len >= 0) {
+                var val = pixels[len];
+                if (val < 0) {
+                    val = 0;
+                } else if (val > 1) {
+                    val = 1;
+                }
+                npixels[len] = val * 255;
+            }
+
+            pixels = npixels;
+        }
+
+        var canvas = document.createElement('canvas');
+        canvas.width = width;
+        canvas.height = height;
+
+        var ctx = canvas.getContext('2d');
+        if (!ctx) {
+            return null;
+        }
+
+        var imageData = ctx.createImageData(width, height);
+        var castData = <any>imageData.data;
+        castData.set(pixels);
+        ctx.putImageData(imageData, 0, 0);
+
+        if (internalTexture.invertY) {
+            var canvas2 = document.createElement('canvas');
+            canvas2.width = width;
+            canvas2.height = height;
+
+            var ctx2 = canvas2.getContext('2d');
+            if (!ctx2) {
+                return null;
+            }
+
+            ctx2.translate(0, height);
+            ctx2.scale(1, -1);
+            ctx2.drawImage(canvas, 0, 0);
+
+            return canvas2.toDataURL('image/png');
+        }
+
+        return canvas.toDataURL('image/png');
+    }
+}

+ 2 - 1
src/Misc/index.ts

@@ -51,4 +51,5 @@ export * from "./dataStorage";
 export * from "./sceneRecorder";
 export * from "./khronosTextureContainer2";
 export * from "./trajectoryClassifier";
-export * from './timer';
+export * from './timer';
+export * from "./copyTools";