Przeglądaj źródła

Merge pull request #7425 from bilkusg/master

Add new RIG_MODE_STEREOSCOPIC_INTERLACED mode for 3d monitors
David Catuhe 5 lat temu
rodzic
commit
dd2863f5b9

+ 3 - 3
src/Cameras/RigModes/stereoscopicRigMode.ts

@@ -1,10 +1,10 @@
 import { Camera } from "../camera";
 import { PassPostProcess } from "../../PostProcesses/passPostProcess";
-import { StereoscopicInterlacePostProcess } from "../../PostProcesses/stereoscopicInterlacePostProcess";
+import { StereoscopicInterlacePostProcessI } from "../../PostProcesses/stereoscopicInterlacePostProcess";
 
 Camera._setStereoscopicRigMode = function(camera: Camera) {
     var isStereoscopicHoriz = camera.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL || camera.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED;
-
+    var isStereoscopicInterlaced = camera.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_INTERLACED;
     camera._rigCameras[0]._rigPostProcess = new PassPostProcess(camera.name + "_passthru", 1.0, camera._rigCameras[0]);
-    camera._rigCameras[1]._rigPostProcess = new StereoscopicInterlacePostProcess(camera.name + "_stereoInterlace", camera._rigCameras, isStereoscopicHoriz);
+    camera._rigCameras[1]._rigPostProcess = new StereoscopicInterlacePostProcessI(camera.name + "_stereoInterlace", camera._rigCameras, isStereoscopicHoriz, isStereoscopicInterlaced);
 };

+ 2 - 0
src/Cameras/arcRotateCamera.ts

@@ -1118,6 +1118,7 @@ export class ArcRotateCamera extends TargetCamera {
             case Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH:
             case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL:
             case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
+            case Camera.RIG_MODE_STEREOSCOPIC_INTERLACED:
             case Camera.RIG_MODE_VR:
                 alphaShift = this._cameraRigParams.stereoHalfAngle * (cameraIndex === 0 ? 1 : -1);
                 break;
@@ -1145,6 +1146,7 @@ export class ArcRotateCamera extends TargetCamera {
             case Camera.RIG_MODE_STEREOSCOPIC_ANAGLYPH:
             case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL:
             case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
+            case Camera.RIG_MODE_STEREOSCOPIC_INTERLACED:
             case Camera.RIG_MODE_VR:
                 camLeft.alpha = this.alpha - this._cameraRigParams.stereoHalfAngle;
                 camRight.alpha = this.alpha + this._cameraRigParams.stereoHalfAngle;

+ 6 - 1
src/Cameras/camera.ts

@@ -78,6 +78,10 @@ export class Camera extends Node {
      */
     public static readonly RIG_MODE_STEREOSCOPIC_OVERUNDER = 13;
     /**
+     * Defines that both eyes of the camera will be rendered on successive lines interlaced for passive 3d monitors.
+     */
+    public static readonly RIG_MODE_STEREOSCOPIC_INTERLACED = 14;
+    /**
      * Defines that both eyes of the camera should be renderered in a VR mode (carbox).
      */
     public static readonly RIG_MODE_VR = 20;
@@ -1003,7 +1007,8 @@ export class Camera extends Node {
             case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL:
             case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED:
             case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
-                Camera._setStereoscopicRigMode(this);
+            case Camera.RIG_MODE_STEREOSCOPIC_INTERLACED:
+                    Camera._setStereoscopicRigMode(this);
                 break;
             case Camera.RIG_MODE_VR:
                 Camera._setVRRigMode(this, rigParams);

+ 1 - 0
src/Cameras/targetCamera.ts

@@ -458,6 +458,7 @@ export class TargetCamera extends Camera {
             case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_PARALLEL:
             case Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED:
             case Camera.RIG_MODE_STEREOSCOPIC_OVERUNDER:
+            case Camera.RIG_MODE_STEREOSCOPIC_INTERLACED:
                 //provisionnaly using _cameraRigParams.stereoHalfAngle instead of calculations based on _cameraRigParams.interaxialDistance:
                 var leftSign = (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED) ? 1 : -1;
                 var rightSign = (this.cameraRigMode === Camera.RIG_MODE_STEREOSCOPIC_SIDEBYSIDE_CROSSEYED) ? -1 : 1;

+ 33 - 1
src/PostProcesses/stereoscopicInterlacePostProcess.ts

@@ -8,6 +8,38 @@ import { Engine } from "../Engines/engine";
 import "../Shaders/stereoscopicInterlace.fragment";
 
 /**
+ * StereoscopicInterlacePostProcessI used to render stereo views from a rigged camera with support for alternate line interlacing
+ */
+export class StereoscopicInterlacePostProcessI extends PostProcess {
+    private _stepSize: Vector2;
+    private _passedProcess: Nullable<PostProcess>;
+
+    /**
+     * Initializes a StereoscopicInterlacePostProcessI
+     * @param name The name of the effect.
+     * @param rigCameras The rig cameras to be appled to the post process
+     * @param isStereoscopicHoriz If the rendered results are horizontal or vertical
+     * @param isStereoscopicInterlaced If the rendered results are alternate line interlaced
+     * @param samplingMode The sampling mode to be used when computing the pass. (default: 0)
+     * @param engine The engine which the post process will be applied. (default: current engine)
+     * @param reusable If the post process can be reused on the same frame. (default: false)
+     */
+    constructor(name: string, rigCameras: Camera[], isStereoscopicHoriz: boolean, isStereoscopicInterlaced: boolean, samplingMode?: number, engine?: Engine, reusable?: boolean) {
+        super(name, "stereoscopicInterlace", ['stepSize'], ['camASampler'], 1, rigCameras[1], samplingMode, engine, reusable, isStereoscopicInterlaced ? "#define IS_STEREOSCOPIC_INTERLACED 1" : isStereoscopicHoriz ? "#define IS_STEREOSCOPIC_HORIZ 1" : undefined);
+
+        this._passedProcess = rigCameras[0]._rigPostProcess;
+        this._stepSize = new Vector2(1 / this.width, 1 / this.height);
+
+        this.onSizeChangedObservable.add(() => {
+            this._stepSize = new Vector2(1 / this.width, 1 / this.height);
+        });
+        this.onApplyObservable.add((effect: Effect) => {
+            effect.setTextureFromPostProcess("camASampler", this._passedProcess);
+            effect.setFloat2("stepSize", this._stepSize.x, this._stepSize.y);
+        });
+    }
+}
+/**
  * StereoscopicInterlacePostProcess used to render stereo views from a rigged camera
  */
 export class StereoscopicInterlacePostProcess extends PostProcess {
@@ -37,4 +69,4 @@ export class StereoscopicInterlacePostProcess extends PostProcess {
             effect.setFloat2("stepSize", this._stepSize.x, this._stepSize.y);
         });
     }
-}
+}

+ 21 - 8
src/Shaders/stereoscopicInterlace.fragment.fx

@@ -7,6 +7,7 @@ uniform vec2 stepSize;
 
 void main(void)
 {
+    bool useCamA;
     bool useCamB;
     vec2 texCoord1;
     vec2 texCoord2;
@@ -15,23 +16,35 @@ void main(void)
     vec3 frag2;
     
 #ifdef IS_STEREOSCOPIC_HORIZ
-	    useCamB = vUV.x > 0.5;
-	    texCoord1 = vec2(useCamB ? (vUV.x - 0.5) * 2.0 : vUV.x * 2.0, vUV.y);
-	    texCoord2 = vec2(texCoord1.x + stepSize.x, vUV.y);
+            useCamB = vUV.x > 0.5;
+            useCamA = !useCamB;
+            texCoord1 = vec2(useCamB ? (vUV.x - 0.5) * 2.0 : vUV.x * 2.0, vUV.y);
+            texCoord2 = vec2(texCoord1.x + stepSize.x, vUV.y);
 #else
-	    useCamB = vUV.y > 0.5;
-	    texCoord1 = vec2(vUV.x, useCamB ? (vUV.y - 0.5) * 2.0 : vUV.y * 2.0);
-	    texCoord2 = vec2(vUV.x, texCoord1.y + stepSize.y);
+#ifdef IS_STEREOSCOPIC_INTERLACED
+            float rowNum = floor(vUV.y / stepSize.y);
+            useCamA = mod(rowNum,2.0) == 1.0;
+            useCamB = mod(rowNum,2.0) == 0.0;
+            texCoord1 = vec2(vUV.x, vUV.y);
+            texCoord2 = vec2(vUV.x, vUV.y);
+#else
+            useCamB = vUV.y > 0.5;
+            useCamA = !useCamB;
+            texCoord1 = vec2(vUV.x, useCamB ? (vUV.y - 0.5) * 2.0 : vUV.y * 2.0);
+            texCoord2 = vec2(vUV.x, texCoord1.y + stepSize.y);
+#endif
 #endif
     
     // cannot assign a sampler to a variable, so must duplicate texture accesses
     if (useCamB){
         frag1 = texture2D(textureSampler, texCoord1).rgb;
         frag2 = texture2D(textureSampler, texCoord2).rgb;
-    }else{
+    }else if (useCamA){
         frag1 = texture2D(camASampler   , texCoord1).rgb;
         frag2 = texture2D(camASampler   , texCoord2).rgb;
+    }else {
+        discard;
     }
     
     gl_FragColor = vec4((frag1 + frag2) / TWO, 1.0);
-}
+}