瀏覽代碼

Non uniform scale (as well as dev from yesterday) (#1279)

* Text2DModelRenderCache now handles correctly the lifetime of the shared FontTexture, making things working after a dispose called on Text2d.

FontTexture has now two new methods: inc/decCachedFontTextureCounter to extend/reduce the lifetime of the shared FontTexture retrieved with GetCachedFontTexture.

* Don't change DepthWrite during rendering of Primitives (looks like an old bug fix...)

* Fix Sprite2D rendering with alpha

* Adding non uniform scale through the scaleX and scaleY properties.
Loïc Baumann 9 年之前
父節點
當前提交
65fb6b1ef4

+ 6 - 4
src/Canvas2d/babylon.ellipse2d.ts

@@ -45,7 +45,7 @@
                 let pid = context.groupInfoPartData[partIndex];
 
                 if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                    engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                    engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
                 }
 
                 let effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
@@ -77,7 +77,7 @@
                 let pid = context.groupInfoPartData[partIndex];
 
                 if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                    engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                    engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
                 }
 
                 let effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
@@ -104,7 +104,7 @@
                 }
             }
 
-            engine.setAlphaMode(curAlphaMode);
+            engine.setAlphaMode(curAlphaMode, true);
 
             if (this.effectFill && this.effectBorder) {
                 engine.setDepthFunction(depthFunction);
@@ -228,7 +228,7 @@
          * - id: a text identifier, for information purpose
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
-         * - scale: the initial scale of the primitive. default is 1
+         * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - origin: define the normalized origin point location, default [0.5;0.5]
          * - size: the size of the group. Alternatively the width and height properties can be set. Default will be [10;10].
@@ -262,6 +262,8 @@
             y                 ?: number,
             rotation          ?: number,
             scale             ?: number,
+            scaleX            ?: number,
+            scaleY            ?: number,
             opacity           ?: number,
             origin            ?: Vector2,
             size              ?: Size,

+ 4 - 1
src/Canvas2d/babylon.group2d.ts

@@ -34,7 +34,7 @@
          * - id a text identifier, for information purpose
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
-         * - scale: the initial scale of the primitive. default is 1
+         * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - origin: define the normalized origin point location, default [0.5;0.5]
          * - size: the size of the group. Alternatively the width and height properties can be set. If null the size will be computed from its content, default is null.
@@ -64,6 +64,9 @@
             position          ?: Vector2,
             x                 ?: number,
             y                 ?: number,
+            scale             ?: number,
+            scaleX            ?: number,
+            scaleY            ?: number,
             trackNode         ?: Node,
             opacity           ?: number,
             origin            ?: Vector2,

+ 6 - 4
src/Canvas2d/babylon.lines2d.ts

@@ -44,7 +44,7 @@
                 let pid = context.groupInfoPartData[partIndex];
 
                 if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                    engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                    engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
                 }
 
                 let effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
@@ -76,7 +76,7 @@
                 let pid = context.groupInfoPartData[partIndex];
 
                 if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                    engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                    engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
                 }
 
                 let effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
@@ -103,7 +103,7 @@
                 }
             }
 
-            engine.setAlphaMode(curAlphaMode);
+            engine.setAlphaMode(curAlphaMode, true);
 
             if (this.effectFill && this.effectBorder) {
                 engine.setDepthFunction(depthFunction);
@@ -394,7 +394,7 @@
          * - id a text identifier, for information purpose
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
-         * - scale: the initial scale of the primitive. default is 1
+         * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - origin: define the normalized origin point location, default [0.5;0.5]
          * - fillThickness: the thickness of the fill part of the line, can be null to draw nothing (but a border brush must be given), default is 1.
@@ -430,6 +430,8 @@
             y                 ?: number,
             rotation          ?: number,
             scale             ?: number,
+            scaleX            ?: number,
+            scaleY            ?: number,
             opacity           ?: number,
             origin            ?: Vector2,
             fillThickness     ?: number,

+ 56 - 9
src/Canvas2d/babylon.prim2dBase.ts

@@ -1290,7 +1290,7 @@
      * Base class for a Primitive of the Canvas2D feature
      */
     export class Prim2DBase extends SmartPropertyPrim {
-        static PRIM2DBASE_PROPCOUNT: number = 15;
+        static PRIM2DBASE_PROPCOUNT: number = 16;
         public  static _bigInt = Math.pow(2, 30);
 
         constructor(settings: {
@@ -1302,6 +1302,8 @@
             y?: number,
             rotation?: number,
             scale?: number,
+            scaleX?: number,
+            scaleY?: number,
             opacity?: number,
             origin?: Vector2,
             layoutEngine?: LayoutEngineBase | string,
@@ -1354,6 +1356,7 @@
             // Fields initialization
             this._layoutEngine = CanvasLayoutEngine.Singleton;
             this._size = null; //Size.Zero();
+            this._scale = new Vector2(1, 1);
             this._actualSize = null;
             this._boundingSize = Size.Zero();
             this._layoutArea = Size.Zero();
@@ -1429,7 +1432,17 @@
                 this._position = null;
             }
             this.rotation = (settings.rotation == null) ? 0 : settings.rotation;
-            this.scale = (settings.scale == null) ? 1 : settings.scale;
+
+            if (settings.scale != null) {
+                this.scale = settings.scale;
+            } else {
+                if (settings.scaleX != null) {
+                    this.scaleX = settings.scaleX;
+                }
+                if (settings.scaleY != null) {
+                    this.scaleY = settings.scaleY;
+                }
+            }
             this.levelVisible = (settings.isVisible == null) ? true : settings.isVisible;
             this.origin = settings.origin || new Vector2(0.5, 0.5);
 
@@ -1622,6 +1635,16 @@
         public static opacityProperty: Prim2DPropInfo;
 
 
+        /**
+         * Metadata of the scaleX property
+         */
+        public static scaleXProperty: Prim2DPropInfo;
+
+        /**
+         * Metadata of the scaleY property
+         */
+        public static scaleYProperty: Prim2DPropInfo;
+
         @instanceLevelProperty(1, pi => Prim2DBase.actualPositionProperty = pi, false, false, true)
         /**
          * Return the position where the primitive is rendered in the Canvas, this position may be different than the one returned by the position property due to layout/alignment/margin/padding computing
@@ -1837,14 +1860,14 @@
 
         @instanceLevelProperty(5, pi => Prim2DBase.scaleProperty = pi, false, true)
         /**
-         * Uniform scale applied on the primitive
+         * Uniform scale applied on the primitive. If a non-uniform scale is applied through scaleX/scaleY property the getter of this property will return scaleX.
          */
         public set scale(value: number) {
-            this._scale = value;
+            this._scale.x = this._scale.y = value;
         }
 
         public get scale(): number {
-            return this._scale;
+            return this._scale.x;
         }
 
         /**
@@ -2060,6 +2083,30 @@
             this._spreadActualOpacityChanged();
         }
 
+        @instanceLevelProperty(14, pi => Prim2DBase.scaleXProperty = pi, false, true)
+        /**
+         * Scale applied on the X axis of the primitive
+         */
+        public set scaleX(value: number) {
+            this._scale.x = value;
+        }
+
+        public get scaleX(): number {
+            return this._scale.x;
+        }
+
+        @instanceLevelProperty(15, pi => Prim2DBase.scaleYProperty = pi, false, true)
+        /**
+         * Scale applied on the Y axis of the primitive
+         */
+        public set scaleY(value: number) {
+            this._scale.y = value;
+        }
+
+        public get scaleY(): number {
+            return this._scale.y;
+        }
+
         public get actualOpacity(): number {
             if (this._isFlagSet(SmartPropertyPrim.flagActualOpacityDirty)) {
                 let cur = this.parent;
@@ -2548,7 +2595,7 @@
         private static _v0: Vector2 = Vector2.Zero();   // Must stay with the value 0,0
 
         private _updateLocalTransform(): boolean {
-            let tflags = Prim2DBase.actualPositionProperty.flagId | Prim2DBase.rotationProperty.flagId | Prim2DBase.scaleProperty.flagId | Prim2DBase.originProperty.flagId;
+            let tflags = Prim2DBase.actualPositionProperty.flagId | Prim2DBase.rotationProperty.flagId | Prim2DBase.scaleProperty.flagId | Prim2DBase.scaleXProperty.flagId | Prim2DBase.scaleYProperty.flagId | Prim2DBase.originProperty.flagId;
             if (this.checkPropertiesDirty(tflags)) {
                 if (this.owner) {
                     this.owner.addupdateLocalTransformCounter(1);
@@ -2559,7 +2606,7 @@
                 let pos = this.position;
 
                 if (this._origin.x === 0 && this._origin.y === 0) {
-                    local = Matrix.Compose(new Vector3(this._scale, this._scale, 1), rot, new Vector3(pos.x, pos.y, 0));
+                    local = Matrix.Compose(new Vector3(this._scale.x, this._scale.y, 1), rot, new Vector3(pos.x, pos.y, 0));
                     this._localTransform = local;
                 } else {
                     // -Origin offset
@@ -2571,7 +2618,7 @@
                     Prim2DBase._t0.multiplyToRef(Prim2DBase._t1, Prim2DBase._t2);
 
                     // -Origin * rotation * scale
-                    Matrix.ScalingToRef(this._scale, this._scale, 1, Prim2DBase._t0);
+                    Matrix.ScalingToRef(this._scale.x, this._scale.y, 1, Prim2DBase._t0);
                     Prim2DBase._t2.multiplyToRef(Prim2DBase._t0, Prim2DBase._t1);
 
                     // -Origin * rotation * scale * (Origin + Position)
@@ -3045,7 +3092,7 @@
         private _layoutArea: Size;
         private _contentArea: Size;
         private _rotation: number;
-        private _scale: number;
+        private _scale: Vector2;
         private _origin: Vector2;
         protected _opacity: number;
         private _actualOpacity: number;

+ 6 - 4
src/Canvas2d/babylon.rectangle2d.ts

@@ -45,7 +45,7 @@
                 let pid = context.groupInfoPartData[partIndex];
 
                 if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                    engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                    engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
                 }
 
                 let effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
@@ -77,7 +77,7 @@
                 let pid = context.groupInfoPartData[partIndex];
 
                 if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                    engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                    engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
                 }
 
                 let effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
@@ -104,7 +104,7 @@
                 }
             }
 
-            engine.setAlphaMode(curAlphaMode);
+            engine.setAlphaMode(curAlphaMode, true);
 
             if (this.effectFill && this.effectBorder) {
                 engine.setDepthFunction(depthFunction);
@@ -312,7 +312,7 @@
          * - id a text identifier, for information purpose
          * - position: the X & Y positions relative to its parent. Alternatively the x and y settings can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
-         * - scale: the initial scale of the primitive. default is 1
+         * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - origin: define the normalized origin point location, default [0.5;0.5]
          * - size: the size of the group. Alternatively the width and height settings can be set. Default will be [10;10].
@@ -345,6 +345,8 @@
             y                 ?: number,
             rotation          ?: number,
             scale             ?: number,
+            scaleX            ?: number,
+            scaleY            ?: number,
             opacity           ?: number,
             origin            ?: Vector2,
             size              ?: Size,

+ 5 - 3
src/Canvas2d/babylon.sprite2d.ts

@@ -29,7 +29,7 @@
             engine.bindBuffersDirectly(this.vb, this.ib, [1], 4, effect);
 
             if (context.renderMode !== Render2DContext.RenderModeOpaque) {
-                engine.setAlphaMode(Engine.ALPHA_COMBINE);
+                engine.setAlphaMode(Engine.ALPHA_COMBINE, true);
             }
 
             let pid = context.groupInfoPartData[0];
@@ -51,7 +51,7 @@
                 }
             }
 
-            engine.setAlphaMode(cur);
+            engine.setAlphaMode(cur, true);
 
             return true;
         }
@@ -239,7 +239,7 @@
          * - id a text identifier, for information purpose
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
-         * - scale: the initial scale of the primitive. default is 1
+         * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - origin: define the normalized origin point location, default [0.5;0.5]
          * - spriteSize: the size of the sprite (in pixels), if null the size of the given texture will be used, default is null.
@@ -272,6 +272,8 @@
             y?: number,
             rotation?: number,
             scale?: number,
+            scaleX?: number,
+            scaleY?: number,
             opacity?: number,
             origin?: Vector2,
             spriteSize?: Size,

+ 6 - 3
src/Canvas2d/babylon.text2d.ts

@@ -51,7 +51,7 @@
                 }
             }
 
-            engine.setAlphaMode(curAlphaMode);
+            engine.setAlphaMode(curAlphaMode, true);
 
             return true;
         }
@@ -72,7 +72,7 @@
             }
 
             if (this.fontTexture) {
-                this.fontTexture.dispose();
+                this.fontTexture.decCachedFontTextureCounter();
                 this.fontTexture = null;
             }
 
@@ -265,7 +265,7 @@
          * - id a text identifier, for information purpose
          * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
          * - rotation: the initial rotation (in radian) of the primitive. default is 0
-         * - scale: the initial scale of the primitive. default is 1
+         * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
          * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
          * - origin: define the normalized origin point location, default [0.5;0.5]
          * - fontName: the name/size/style of the font to use, following the CSS notation. Default is "12pt Arial".
@@ -299,6 +299,8 @@
             y                 ?: number,
             rotation          ?: number,
             scale             ?: number,
+            scaleX            ?: number,
+            scaleY            ?: number,
             opacity           ?: number,
             origin            ?: Vector2,
             fontName          ?: string,
@@ -354,6 +356,7 @@
             let engine = this.owner.engine;
 
             renderCache.fontTexture = this.fontTexture;
+            renderCache.fontTexture.incCachedFontTextureCounter();
 
             let vb = new Float32Array(4);
             for (let i = 0; i < 4; i++) {

+ 26 - 0
src/Materials/Textures/babylon.fontTexture.ts

@@ -35,6 +35,7 @@
         private _spaceWidthSuper;
         private _usedCounter = 1;
         private _superSample: boolean;
+        private _cachedFontId: string;
 
         public get isSuperSampled(): boolean {
             return this._superSample;
@@ -64,6 +65,7 @@
             }
 
             ft = new FontTexture(null, fontName, scene, supersample ? 100 : 200, Texture.BILINEAR_SAMPLINGMODE, supersample);
+            ft._cachedFontId = lfn;
             dic.add(lfn, ft);
 
             return ft;
@@ -115,6 +117,7 @@
             this._context = this._canvas.getContext("2d");
             this._context.font = font;
             this._context.fillStyle = "white";
+            this._cachedFontId = null;
 
             var res = this.getFontHeight(font);
             this._lineHeightSuper = res.height;
@@ -323,5 +326,28 @@
         public clone(): FontTexture {
             return null;
         }
+
+        /**
+         * For FontTexture retrieved using GetCachedFontTexture, use this method when you transfer this object's lifetime to another party in order to share this resource.
+         * When the other party is done with this object, decCachedFontTextureCounter must be called.
+         */
+        public incCachedFontTextureCounter() {
+            ++this._usedCounter;
+        }
+
+        /**
+         * Use this method only in conjunction with incCachedFontTextureCounter, call it when you no longer need to use this shared resource.
+         */
+        public decCachedFontTextureCounter() {
+            let s = <any>this.getScene();
+            let dic = <StringDictionary<FontTexture>>s.__fontTextureCache__;
+            if (!dic) {
+                return;
+            }
+            if (--this._usedCounter === 0) {
+                dic.remove(this._cachedFontId);
+                this.dispose();
+            }         
+        }
     }
 } 

+ 1 - 1
src/Shaders/sprite2d.fragment.fx

@@ -4,7 +4,7 @@ uniform sampler2D diffuseSampler;
 
 void main(void) {
 	vec4 color = texture2D(diffuseSampler, vUV);
-	if (color.a == 0.05) {
+	if (color.a < 0.05) {
 		discard;
 	}
 	color.a *= vOpacity;