Browse Source

Added fov zoom functionality to video dome and backgroundMaterial, upgraded videoDome capabilities.

David 7 years ago
parent
commit
1d9a4ab14a

+ 22 - 6
src/Helpers/babylon.videoDome.ts

@@ -10,29 +10,42 @@ module BABYLON {
         /**
          * The video texture being displayed on the sphere
          */
-        private _videoTexture: VideoTexture;
+        protected _videoTexture: VideoTexture;
 
         /**
          * The skybox material
          */
-        private _material: BackgroundMaterial;
+        protected _material: BackgroundMaterial;
 
         /**
          * The surface used for the skybox
          */
-        private _mesh: Mesh;
+        protected _mesh: Mesh;
+
+        /**
+         * The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
+         * Also see the options.resolution property.
+         */
+        public get fovMultiplier(): number {
+            return this._material.fovMultiplier;
+        }
+        public set fovMultiplier(value: number) {
+            this._material.fovMultiplier = value;
+        }
 
         /**
          * Create an instance of this class and pass through the parameters to the relevant classes, VideoTexture, StandardMaterial, and Mesh.
          * @param name Element's name, child elements will append suffixes for their own names.
          * @param urlsOrVideo
          * @param options An object containing optional or exposed sub element properties:
+         * @param options **resolution=12** Integer, lower resolutions have more artifacts at extreme fovs
          * @param options **clickToPlay=false** Add a click to play listener to the video, does not prevent autoplay.
          * @param options **autoPlay=true** Automatically attempt to being playing the video.
          * @param options **loop=true** Automatically loop video on end.
          * @param options **size=1000** Physical radius to create the dome at, defaults to approximately half the far clip plane.
          */
         constructor(name: string, urlsOrVideo: string[] | HTMLVideoElement, options: {
+            resolution?: number,
             clickToPlay?: boolean,
             autoPlay?: boolean,
             loop?: boolean,
@@ -42,6 +55,7 @@ module BABYLON {
 
             // set defaults and manage values
             name = name || "videoDome";
+            options.resolution = (Math.abs(options.resolution as any) | 0) || 12;
             options.clickToPlay = Boolean(options.clickToPlay);
             options.autoPlay = options.autoPlay === undefined ? true : Boolean(options.autoPlay);
             options.loop = options.loop === undefined ? true : Boolean(options.loop);
@@ -52,14 +66,16 @@ module BABYLON {
             let material = this._material = new BABYLON.BackgroundMaterial(name+"_material", scene);
             this._videoTexture = new BABYLON.VideoTexture(name+"_texture", urlsOrVideo, scene, false, false, Texture.TRILINEAR_SAMPLINGMODE, tempOptions);
             this._mesh = BABYLON.MeshBuilder.CreateIcoSphere(name+"_mesh", {
+                flat: false, // saves on vertex data
                 radius: options.size,
-                subdivisions: 1,
-                sideOrientation: BABYLON.Mesh.BACKSIDE
-            }, scene); // needs to be inside out
+                subdivisions: options.resolution,
+                sideOrientation: BABYLON.Mesh.BACKSIDE // needs to be inside out
+            }, scene);
 
             // configure material
             this._videoTexture.coordinatesMode = BABYLON.Texture.FIXED_EQUIRECTANGULAR_MIRRORED_MODE; // matches src
             material.reflectionTexture = this._videoTexture;
+            material.fovMultiplier = 1.0;
 
             // configure mesh
             this._mesh.material = material;

+ 21 - 1
src/Materials/Background/babylon.backgroundMaterial.ts

@@ -329,6 +329,23 @@
         @expandToProperty("_markAllSubMeshesAsTexturesDirty")
         public enableNoise: boolean = false;
 
+        /** See getter/setter */
+        protected _fovMultiplier: number = 1.0;
+
+        /**
+         * The current fov(field of view) multiplier, 0.0 - 2.0. Defaults to 1.0. Lower values "zoom in" and higher values "zoom out".
+         * Best used when trying to implement visual zoom effects like fish-eye or binoculars while not adjusting camera fov.
+         * Recommended to be keep at 1.0 except for special cases.
+         */
+        public get fovMultiplier(): number {
+            return this._fovMultiplier;
+        }
+        public set fovMultiplier(value: number) {
+            if (isNaN(value)) {
+                value = 1.0;
+            }
+            this._fovMultiplier = Math.max(0.0, Math.min(2.0, value));
+        }
 
         /**
          * Number of Simultaneous lights allowed on the material.
@@ -755,7 +772,7 @@
                     "vClipPlane", "mBones",
 
                     "vPrimaryColor", "vSecondaryColor", "vTertiaryColor",
-                    "vReflectionInfos", "reflectionMatrix", "vReflectionMicrosurfaceInfos",
+                    "vReflectionInfos", "reflectionMatrix", "vReflectionMicrosurfaceInfos", "fFovMultiplier",
 
                     "shadowLevel", "alpha",
 
@@ -825,6 +842,7 @@
             this._uniformBuffer.addUniform("diffuseMatrix", 16);
             this._uniformBuffer.addUniform("reflectionMatrix", 16);
             this._uniformBuffer.addUniform("vReflectionMicrosurfaceInfos", 3);
+            this._uniformBuffer.addUniform("fFovMultiplier", 1);
             this._uniformBuffer.addUniform("pointSize", 1);
             this._uniformBuffer.addUniform("shadowLevel", 1);
             this._uniformBuffer.addUniform("alpha", 1);
@@ -924,6 +942,8 @@
                     this._uniformBuffer.updateColor4("vTertiaryColor", this._tertiaryColor, this._tertiaryLevel);
                 }
 
+                this._uniformBuffer.updateFloat("fFovMultiplier", this._fovMultiplier);
+
                 // Textures
                 if (scene.texturesEnabled) {
                     if (this._diffuseTexture && StandardMaterial.DiffuseTextureEnabled) {

+ 1 - 0
src/Shaders/ShadersInclude/backgroundUboDeclaration.fx

@@ -10,6 +10,7 @@ uniform Material
 	uniform mat4 diffuseMatrix;
 	uniform mat4 reflectionMatrix;
 	uniform vec3 vReflectionMicrosurfaceInfos;
+	uniform float fFovMultiplier;
 
 	uniform float pointSize;
 	uniform float shadowLevel;

+ 1 - 1
src/Shaders/ShadersInclude/reflectionFunction.fx

@@ -1,7 +1,7 @@
 vec3 computeReflectionCoords(vec4 worldPos, vec3 worldNormal)
 {
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
-	vec3 direction = normalize(vDirectionW);
+	vec3 direction = vDirectionW;
 
 	float t = clamp(direction.y * -0.5 + 0.5, 0., 1.0);
 	float s = atan(direction.z, direction.x) * RECIPROCAL_PI2 + 0.5;

+ 12 - 0
src/Shaders/background.vertex.fx

@@ -2,6 +2,8 @@
 
 #include<__decl__backgroundVertex>
 
+#include<helperFunctions>
+
 // Attributes
 attribute vec3 position;
 #ifdef NORMAL
@@ -78,6 +80,16 @@ void main(void) {
 
 #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
     vDirectionW = normalize(vec3(finalWorld * vec4(position, 0.0)));
+
+    if (fFovMultiplier != 1.0) {
+        mat3 screenToWorld = inverseMat3(mat3(finalWorld * viewProjection));
+        vec3 segment = mix(vDirectionW, screenToWorld * vec3(0.0,0.0, 1.0), abs(fFovMultiplier - 1.0));
+        if (fFovMultiplier < 1.0) {
+            vDirectionW = normalize(segment);
+        } else {
+            vDirectionW = normalize(vDirectionW + (vDirectionW - segment));
+        }
+    }
 #endif
 
 #ifndef UV1