Browse Source

First version of WorldSpace Canvas2D, limited, but working: https://trello.com/c/vXEqUzQx

Added get/setDepthFunction to Engine class to save/change/restore depth buffer comparison function.
nockawa 9 years ago
parent
commit
c371180ae0

+ 1 - 0
Tools/Gulp/config.json

@@ -171,6 +171,7 @@
         "../../src/Canvas2d/babylon.sprite2d.js",
         "../../src/Canvas2d/babylon.text2d.js",
         "../../src/Canvas2d/babylon.canvas2d.js",
+        "../../src/Canvas2d/babylon.worldspacecanvas2d.js",
         "../../src/Materials/babylon.shaderMaterial.js",
         "../../src/Tools/babylon.tools.dds.js",
         "../../src/Physics/Plugins/babylon.cannonJSPlugin.js",

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

@@ -15,6 +15,7 @@
     - Unity3D exporter: Added support for export and run (local webserver) ([davrous](https://github.com/davrous), [deltakosh](https://github.com/deltakosh))
     - Moved PBR Material to core ([deltakosh](https://github.com/deltakosh))
     - StandardMaterial.maxSimultaneousLights can define how many dynamic lights the material can handle ([deltakosh](https://github.com/deltakosh))
+	- Introduced Canvas2D feature: a 2D engine to render primitives, sprites in 2D, text. Canvas2D can be displayed in Screen Space (above the 3D scene) or in World Space to be a part of the Scene. [DOC LINK COMES SOON] ([nockawa](https://github.com/nockawa))	
   - **Updates**
     - Added postprocess.enablePixelPerfectMode to avoid texture scaling/stretching when dealing with non-power of 2 resolutions. cannot be used on post-processes chain ([deltakosh](https://github.com/deltakosh))
     - Enabled other post processes to be used when also using a 3D Rig ([jcpalmer](https://github.com/Palmer-JC))

+ 37 - 20
src/Canvas2d/babylon.canvas2d.ts

@@ -48,20 +48,31 @@
         /**
          * Create a new 2D WorldSpace Rendering Canvas, it is a 2D rectangle that has a size (width/height) and a world transformation matrix to place it in the world space.
          * This kind of canvas can't have its Primitives directly drawn in the Viewport, they need to be cached in a bitmap at some point, as a consequence the DONT_CACHE strategy is unavailable. All remaining strategies are supported.
-         * @param engine
-         * @param name
-         * @param transform
-         * @param size
-         * @param cachingStrategy
          */
-        static CreateWorldSpace(scene: Scene, name: string, transform: Matrix, size: Size, cachingStrategy: number = Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS): Canvas2D {
-            if (cachingStrategy === Canvas2D.CACHESTRATEGY_DONTCACHE) {
-                throw new Error("CACHESTRATEGY_DONTCACHE cache Strategy can't be used for WorldSpace Canvas");
+        static CreateWorldSpace(scene: Scene, name: string, position: Vector3, rotation: Quaternion, size: Size, renderScaleFactor: number=1, sideOrientation?: number, cachingStrategy: number = Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS): Canvas2D {
+            if (cachingStrategy !== Canvas2D.CACHESTRATEGY_CANVAS) {
+                throw new Error("Right now only the CACHESTRATEGY_CANVAS cache Strategy is supported for WorldSpace Canvas. More will come soon!");
             }
 
+            //if (cachingStrategy === Canvas2D.CACHESTRATEGY_DONTCACHE) {
+            //    throw new Error("CACHESTRATEGY_DONTCACHE cache Strategy can't be used for WorldSpace Canvas");
+            //}
+
             let c = new Canvas2D();
-            c.setupCanvas(scene, name, size, false, cachingStrategy);
-            c._worldTransform = transform;
+            c.setupCanvas(scene, name, new Size(size.width*renderScaleFactor, size.height*renderScaleFactor), false, cachingStrategy);
+
+            let plane = new WorldSpaceCanvas2d(name, scene, c);
+            let vertexData = VertexData.CreatePlane({ width: size.width/2, height: size.height/2, sideOrientation: sideOrientation });
+            let mtl = new StandardMaterial(name + "_Material", scene);
+
+            c.applyCachedTexture(vertexData, mtl);
+            vertexData.applyToMesh(plane, false);
+
+            mtl.specularColor = new Color3(0, 0, 0);
+            mtl.useAlphaFromDiffuseTexture = true;
+            plane.position = position;
+            plane.rotationQuaternion = rotation;
+            plane.material = mtl;
 
             return c;
         }
@@ -80,20 +91,24 @@
             this._engine = scene.getEngine();
             this._renderingSize = new Size(0, 0);
 
-            if (cachingstrategy !== Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
-                this._background = Rectangle2D.Create(this, "###CANVAS BACKGROUND###", 0, 0, size.width, size.height);
-                this._background.levelVisible = false;
-            }
+            //if (cachingstrategy !== Canvas2D.CACHESTRATEGY_TOPLEVELGROUPS) {
+            //    this._background = Rectangle2D.Create(this, "###CANVAS BACKGROUND###", 0, 0, size.width, size.height);
+            //    this._background.levelVisible = false;
+            //}
             this._isScreeSpace = isScreenSpace;
 
             if (this._isScreeSpace) {
                 this._afterRenderObserver = this._scene.onAfterRenderObservable.add((d, s) => {
                     this.render();
                 });
+            } else {
+                this._beforeRenderObserver = this._scene.onBeforeRenderObservable.add((d, s) => {
+                    this.render();
+                });
             }
 
             this._supprtInstancedArray = this._engine.getCaps().instancedArrays !== null;
-            this._supprtInstancedArray = false; // TODO REMOVE!!!
+//            this._supprtInstancedArray = false; // TODO REMOVE!!!
         }
 
         public dispose(): boolean {
@@ -211,7 +226,6 @@
         private _scene: Scene;
         private _engine: Engine;
         private _isScreeSpace: boolean;
-        private _worldTransform: Matrix;
         private _cachingStrategy: number;
         private _hierarchyMaxDepth: number;
         private _hierarchyLevelZFactor: number;
@@ -285,10 +299,13 @@
             }
 
             // Create a Sprite that will be used to render this cache, the "__cachedSpriteOfGroup__" starting id is a hack to bypass exception throwing in case of the Canvas doesn't normally allows direct primitives
-            let node: PackedRect = res.node;
-            let sprite = Sprite2D.Create(this, `__cachedSpriteOfGroup__${group.id}`, group.position.x, group.position.y, map, node.contentSize, node.pos, false);
-            sprite.origin = Vector2.Zero();
-            res.sprite = sprite;
+            // Don't do it in case of the group being a worldspace canvas (because its texture is bound to a WorldSpaceCanvas node)
+            if (group !== <any>this || this._isScreeSpace) {
+                let node: PackedRect = res.node;
+                let sprite = Sprite2D.Create(this, `__cachedSpriteOfGroup__${group.id}`, group.position.x, group.position.y, map, node.contentSize, node.pos, false);
+                sprite.origin = Vector2.Zero();
+                res.sprite = sprite;
+            }
             return res;
         }
 

+ 21 - 7
src/Canvas2d/babylon.group2d.ts

@@ -37,6 +37,21 @@
             return g;
         }
 
+        applyCachedTexture(vertexData: VertexData, material: StandardMaterial) {
+            this._bindCacheTarget();
+
+            var uv = vertexData.uvs;
+            let nodeuv = this._cacheNode.UVs;
+            for (let i = 0; i < 4; i++) {
+                uv[i * 2 + 0] = nodeuv[i].x;
+                uv[i * 2 + 1] = nodeuv[i].y;
+            }
+
+            material.diffuseTexture = this._cacheTexture;
+            this._cacheTexture.hasAlpha = true;
+            this._unbindCacheTarget();
+        }
+
         /**
          * Create an instance of the Group Primitive.
          * A group act as a container for many sub primitives, if features:
@@ -237,14 +252,13 @@
 
                             v._dirtyInstancesData = false;
                         }
-
-                        // render all the instances of this model, if the render method returns true then our instances are no longer dirty
-                        let renderFailed = !v._modelCache.render(v, context);
-
-                        // Update dirty flag/related
-                        v._dirtyInstancesData = renderFailed;
-                        failedCount += renderFailed ? 1 : 0;
                     }
+                    // render all the instances of this model, if the render method returns true then our instances are no longer dirty
+                    let renderFailed = !v._modelCache.render(v, context);
+
+                    // Update dirty flag/related
+                    v._dirtyInstancesData = renderFailed;
+                    failedCount += renderFailed ? 1 : 0;
                 });
 
                 // The group's content is no longer dirty

+ 8 - 0
src/Canvas2d/babylon.rectangle2d.ts

@@ -21,6 +21,11 @@
 
             var engine = instanceInfo._owner.owner.engine;
 
+            let depthFunction = 0;
+            if (this.effectFill && this.effectBorder) {
+                depthFunction = engine.getDepthFunction();
+                engine.setDepthFunctionToLessOrEqual();
+            }
             if (this.effectFill) {
                 let partIndex = instanceInfo._partIndexFromId.get(Shape2D.SHAPE2D_FILLPARTID.toString());
 
@@ -65,6 +70,9 @@
                     }
                 }
             }
+            if (this.effectFill && this.effectBorder) {
+                engine.setDepthFunction(depthFunction);
+            }
             return true;
         }
     }

+ 11 - 0
src/Canvas2d/babylon.worldSpaceCanvas2d.ts

@@ -0,0 +1,11 @@
+module BABYLON {
+    export class WorldSpaceCanvas2d extends Mesh {
+        constructor(name: string, scene: Scene, canvas: Canvas2D) {
+            super(name, scene);
+
+            this._canvas = canvas;
+        }
+        private _canvas: Canvas2D;
+
+    }
+}

+ 0 - 1
src/Materials/Textures/babylon.mapTexture.ts

@@ -62,7 +62,6 @@
             if (clear) {
                 engine.clear(new Color4(0,0,0,0), true, true);
             }
-//            this._replacedViewport = engine.setDirectViewport(rect.pos.x, rect.pos.y, rect.contentSize.width, rect.contentSize.height);
         }
 
         /**

+ 8 - 0
src/babylon.engine.ts

@@ -592,6 +592,14 @@
             this._drawCalls = 0;
         }
 
+        public getDepthFunction(): number {
+            return this._depthCullingState.depthFunc;
+        }
+
+        public setDepthFunction(depthFunc: number) {
+            this._depthCullingState.depthFunc = depthFunc;
+        }
+
         public setDepthFunctionToGreater(): void {
             this._depthCullingState.depthFunc = this._gl.GREATER;
         }