Browse Source

Canvas 2D: Text2D + Bug Fix

Text2D is now rendering correctly when above a transparent area.

Bug Fix: TransparentSegment are rebuilding correct for multi-part primitives
nockawa 9 years ago
parent
commit
b53152eeca

+ 4 - 4
src/Canvas2d/babylon.canvas2d.ts

@@ -944,7 +944,7 @@
                 id: "ProfileInfoCanvas", cachingStrategy: Canvas2D.CACHESTRATEGY_DONTCACHE, children:
                 [
                     new Rectangle2D({
-                        id: "ProfileBorder", border: "#FFFFFFFF", borderThickness: 2, roundRadius: 5, marginAlignment: "h: left, v: top", margin: "10", padding: "10", children:
+                        id: "ProfileBorder", border: "#FFFFFFFF", borderThickness: 2, roundRadius: 5, fill: "#C04040C0", marginAlignment: "h: left, v: top", margin: "10", padding: "10", children:
                         [
                             new Text2D("Stats", { id: "ProfileInfoText", marginAlignment: "h: left, v: top", fontName: "10pt Lucida Console" })
                         ]
@@ -1002,9 +1002,9 @@
             let format = (v: number) => (Math.round(v*100)/100).toString();
 
             let p = `Draw Calls:\n` +
-                    ` - Opaque:      ${this.drawCallsOpaqueCounter.current}, (avg:${format(this.drawCallsOpaqueCounter.lastSecAverage)}, t:${format(this.drawCallsOpaqueCounter.total)})\n` +
-                    ` - AlphaTest:   ${this.drawCallsAlphaTestCounter.current}, (avg:${format(this.drawCallsAlphaTestCounter.lastSecAverage)}, t:${format(this.drawCallsAlphaTestCounter.total)})\n` +
-                    ` - Transparent: ${this.drawCallsTransparentCounter.current}, (avg:${format(this.drawCallsTransparentCounter.lastSecAverage)}, t:${format(this.drawCallsTransparentCounter.total)})\n` +
+                    ` - Opaque:      ${format(this.drawCallsOpaqueCounter.current)}, (avg:${format(this.drawCallsOpaqueCounter.lastSecAverage)}, t:${format(this.drawCallsOpaqueCounter.total)})\n` +
+                    ` - AlphaTest:   ${format(this.drawCallsAlphaTestCounter.current)}, (avg:${format(this.drawCallsAlphaTestCounter.lastSecAverage)}, t:${format(this.drawCallsAlphaTestCounter.total)})\n` +
+                    ` - Transparent: ${format(this.drawCallsTransparentCounter.current)}, (avg:${format(this.drawCallsTransparentCounter.lastSecAverage)}, t:${format(this.drawCallsTransparentCounter.total)})\n` +
                     `Group Render: ${this.groupRenderCounter.current}, (avg:${format(this.groupRenderCounter.lastSecAverage)}, t:${format(this.groupRenderCounter.total)})\n` + 
                     `Update Transparent Data: ${this.updateTransparentDataCounter.current}, (avg:${format(this.updateTransparentDataCounter.lastSecAverage)}, t:${format(this.updateTransparentDataCounter.total)})\n` + 
                     `Cached Group Render: ${this.cachedGroupRenderCounter.current}, (avg:${format(this.cachedGroupRenderCounter.lastSecAverage)}, t:${format(this.cachedGroupRenderCounter.total)})\n` + 

+ 5 - 32
src/Canvas2d/babylon.group2d.ts

@@ -527,11 +527,6 @@
 
             let rd = this._renderableData;
 
-            // If null, there was no change of ZOrder, we have nothing to do
-            if (rd._firstChangedPrim === null) {
-                return;
-            }
-
             // Sort all the primitive from their depth, max (bottom) to min (top)
             rd._transparentPrimitives.sort((a, b) => b._primitive.actualZOffset - a._primitive.actualZOffset);
 
@@ -543,16 +538,11 @@
                     return false;
                 }
 
-                let tpiZ = tpi._primitive.actualZOffset;
+                //let tpiZ = tpi._primitive.actualZOffset;
 
                 // We've made it so far, the tpi can be part of the segment, add it
                 tpi._transparentSegment = seg;
-
-                // Check if we have to update endZ, a smaller value means one above the current one
-                if (tpiZ < seg.endZ) {
-                    seg.endZ = tpiZ;
-                    seg.endDataIndex = tpi._primitive._getLastIndexInDataBuffer() + 1; // Still exclusive
-                }
+                seg.endDataIndex = tpi._primitive._getPrimitiveLastIndex();
 
                 return true;
             }
@@ -587,8 +577,7 @@
                     ts.groupInsanceInfo = tpi._groupInstanceInfo;
                     let prim = tpi._primitive;
                     ts.startZ = prim.actualZOffset;
-                    ts.startDataIndex = prim._getFirstIndexInDataBuffer();
-                    ts.endDataIndex = prim._getLastIndexInDataBuffer() + 1; // Make it exclusive, more natural to use in a for loop
+                    prim._updateTransparentSegmentIndices(ts);
                     ts.endZ = ts.startZ;
                     tpi._transparentSegment = ts;
                     rd._transparentSegments.push(ts);
@@ -597,7 +586,7 @@
                 prevSeg = tpi._transparentSegment;
             }
 
-            rd._firstChangedPrim = null;
+            //rd._firstChangedPrim = null;
             rd._transparentListChanged = false;
         }
 
@@ -948,7 +937,6 @@
             this._renderGroupInstancesInfo = new StringDictionary<GroupInstanceInfo>();
             this._transparentPrimitives = new Array<TransparentPrimitiveInfo>();
             this._transparentSegments = new Array<TransparentSegment>();
-            this._firstChangedPrim = null;
             this._transparentListChanged = false;
             this._cacheNode = null;
             this._cacheTexture = null;
@@ -1008,8 +996,6 @@
             this._transparentPrimitives.push(tpi);
             this._transparentListChanged = true;
 
-            this.updateSmallestZChangedPrim(tpi);
-
             return tpi;
         }
 
@@ -1018,24 +1004,12 @@
             if (index !== -1) {
                 this._transparentPrimitives.splice(index, 1);
                 this._transparentListChanged = true;
-
-                this.updateSmallestZChangedPrim(tpi);
             }
         }
 
         transparentPrimitiveZChanged(tpi: TransparentPrimitiveInfo) {
             this._transparentListChanged = true;
-            this.updateSmallestZChangedPrim(tpi);
-        }
-
-        updateSmallestZChangedPrim(tpi: TransparentPrimitiveInfo) {
-            if (tpi._primitive) {
-                let newZ = tpi._primitive.actualZOffset;
-                let curZ = this._firstChangedPrim ? this._firstChangedPrim._primitive.actualZOffset : Number.MIN_VALUE;
-                if (newZ > curZ) {
-                    this._firstChangedPrim = tpi;
-                }
-            }
+            //this.updateSmallestZChangedPrim(tpi);
         }
 
         _primDirtyList: Array<Prim2DBase>;
@@ -1054,7 +1028,6 @@
         _transparentListChanged: boolean;
         _transparentPrimitives: Array<TransparentPrimitiveInfo>;
         _transparentSegments: Array<TransparentSegment>;
-        _firstChangedPrim: TransparentPrimitiveInfo;
         _renderingScale: number;
 
     }

+ 1 - 1
src/Canvas2d/babylon.prim2dBase.ts

@@ -1291,7 +1291,7 @@
      */
     export class Prim2DBase extends SmartPropertyPrim {
         static PRIM2DBASE_PROPCOUNT: number = 15;
-        private static _bigInt = Math.pow(2, 30);
+        public  static _bigInt = Math.pow(2, 30);
 
         constructor(settings: {
             parent?: Prim2DBase,

+ 32 - 10
src/Canvas2d/babylon.renderablePrim2d.ts

@@ -253,6 +253,7 @@
             this.curElement = 0;
             this.dataElementCount = dataElementCount;
             this.renderMode = 0;
+            this.arrayLengthChanged = false;
         }
 
         id: number;
@@ -315,11 +316,12 @@
                 return;
             }
 
+            this.arrayLengthChanged = true;
             this.freeElements();
             this._dataElementCount = value;
             this.allocElements();
         }
-
+        arrayLengthChanged: boolean;
         curElement: number;
         renderMode: number;
         dataElements: DynamicFloatArrayElementInfo[];
@@ -595,8 +597,9 @@
 
         private _updateInstanceDataParts(gii: GroupInstanceInfo) {
             // Fetch the GroupInstanceInfo if we don't already have it
+            let rd = this.renderGroup._renderableData;
             if (!gii) {
-                gii = this.renderGroup._renderableData._renderGroupInstancesInfo.get(this.modelKey);
+                gii = rd._renderGroupInstancesInfo.get(this.modelKey);
             }
 
             let isTransparent = this.isTransparent;
@@ -644,11 +647,11 @@
                     if (this.isVisible && !wereTransparent) {
                         if (!this._transparentPrimitiveInfo) {
                             // Add the primitive to the list of transparent ones in the group that render is
-                            this._transparentPrimitiveInfo = this.renderGroup._renderableData.addNewTransparentPrimitiveInfo(this, gii);
+                            this._transparentPrimitiveInfo = rd.addNewTransparentPrimitiveInfo(this, gii);
                         }
                     } else {
                         if (this._transparentPrimitiveInfo) {
-                            this.renderGroup._renderableData.removeTransparentPrimitiveInfo(this._transparentPrimitiveInfo);
+                            rd.removeTransparentPrimitiveInfo(this._transparentPrimitiveInfo);
                             this._transparentPrimitiveInfo = null;
                         }
                     }
@@ -656,6 +659,8 @@
                 }
             }
 
+            let rebuildTrans = false;
+
             // For each Instance Data part, refresh it to update the data in the DynamicFloatArray
             for (let part of this._instanceDataParts) {
                 // Check if we need to allocate data elements (hidden prim which becomes visible again)
@@ -666,18 +671,24 @@
                 InstanceClassInfo._CurCategories = gii.usedShaderCategories[gii.partIndexFromId.get(part.id.toString())];
 
                 // Will return false if the instance should not be rendered (not visible or other any reasons)
+                part.arrayLengthChanged = false;
                 if (!this.refreshInstanceDataPart(part)) {
                     // Free the data element
                     if (part.dataElements) {
                         part.freeElements();
                     }
                 }
+
+                rebuildTrans = rebuildTrans || part.arrayLengthChanged;
             }
             this._instanceDirtyFlags = 0;
 
             // Make the appropriate data dirty
             if (isTransparent) {
                 gii.transparentDirty = true;
+                if (rebuildTrans) {
+                    rd._transparentListChanged = true;
+                }
             } else if (isAlphaTest) {
                 gii.alphaTestDirty = true;
             } else {
@@ -687,22 +698,33 @@
             this._clearFlags(SmartPropertyPrim.flagVisibilityChanged);    // Reset the flag as we've handled the case            
         }
 
-        public _getFirstIndexInDataBuffer(): number {
+        _updateTransparentSegmentIndices(ts: TransparentSegment) {
+            let minOff = Prim2DBase._bigInt;
+            let maxOff = 0;
+
             for (let part of this._instanceDataParts) {
                 if (part) {
-                    return part.dataElements[0].offset / part.dataBuffer.stride;
+                    for (let el of part.dataElements) {
+                        minOff = Math.min(minOff, el.offset);
+                        maxOff = Math.max(maxOff, el.offset);
+                    }
+                    ts.startDataIndex = minOff / part.dataBuffer.stride;
+                    ts.endDataIndex = (maxOff / part.dataBuffer.stride) + 1; // +1 for exclusive
                 }
             }
-            return null;
         }
 
-        public _getLastIndexInDataBuffer(): number {
+        _getPrimitiveLastIndex(): number {
+            let maxOff = 0;
+
             for (let part of this._instanceDataParts) {
                 if (part) {
-                    return part.dataElements[part.dataElements.length-1].offset / part.dataBuffer.stride;
+                    for (let el of part.dataElements) {
+                        maxOff = Math.max(maxOff, el.offset);
+                    }
+                    return (maxOff / part.dataBuffer.stride) + 1; // +1 for exclusive
                 }
             }
-            return null;
         }
 
         // This internal method is mainly used for transparency processing

+ 1 - 1
src/Canvas2d/babylon.text2d.ts

@@ -336,7 +336,7 @@
             this._textSize        = null;
             this.text             = text;
             this.size             = (settings.size==null) ? null : settings.size;
-            this.isAlphaTest      = true;
+            this.isTransparent    = true;
         }
 
         protected levelIntersect(intersectInfo: IntersectInfo2D): boolean {