3D stereo vision based on CesiumVR

Keywords: Javascript

Overall thinking


  1. On the basis of VR module, the parallax is adjusted to change with the distance;
  2. When the left and right screens are divided, the left and right screens need to be compressed 1 / 2 horizontally, because 3D-TV will stretch when merging the left and right format images;
  3. The position of the camera on the left screen has changed relative to the original (right screen) camera, so it is necessary to re judge the slice in the field of view of the camera on the left screen and re render (to solve the problem of black slice).


Code part

  1. Parallax adjustment and split screen lateral compression
      function updateAndExecuteCommands(scene, passState, backgroundColor) {    
       ......    var near = camera.frustum.near;    var fo = near * 5.0;    var eyeSeparation = fo / 30.0;    //var eyeTranslation = Cartesian3.multiplyByScalar(savedCamera.right, eyeSeparation * 0.5, scratchEyeTranslation);    //Modify to make parallax change with camera height    //var modifyEyeSeparation = eyeSeparation * 0.5 * savedCamera.position.z ;   //savedCamera.getMagnitude() gets the distance from the center    var modifyEyeSeparation = eyeSeparation * 0.5 * savedCamera.getMagnitude() ;    var eyeTranslation = Cartesian3.multiplyByScalar(savedCamera.right, modifyEyeSeparation, scratchEyeTranslation);    viewport.x = passState.viewport.width;    // camera.frustum.aspectRatio = viewport.width / viewport.height;    // Modify to make the sphere shrink laterally in VR mode    camera.frustum.aspectRatio = viewport.width*2 / viewport.height;    var offset = 0.5 * eyeSeparation * near / fo;    //Cartesian3.add(savedCamera.position, eyeTranslation, camera.position);    camera.frustum.xOffset = offset;
      executeCommands(scene, passState);             

           viewport.x = 0;
          Cartesian3.subtract(savedCamera.position, eyeTranslation, camera.position);
          camera.frustum.xOffset = -offset;
          //The camera position changes, so the slice to be rendered changes; so recalculate the slice to be rendered and render (this part needs to be improved)       
          executeCommands(scene, passState);
          Camera.clone(savedCamera, camera);

2. Render the left screen (camera offset scene) again (temporary solution, render the scene outside the camera, the existing problem: the efficiency is too low)

  CullingVolume.prototype.computeVisibility = function(boundingVolume) {
      if (!defined(boundingVolume)) {
          throw new DeveloperError('boundingVolume is required.');
      var planes = this.planes;
      var intersecting = true;
      for (var k = 0, len = planes.length; k < len; ++k) {
          var result = boundingVolume.intersectPlane(Plane.fromCartesian4(planes[k], scratchPlane));
          if (result === Intersect.OUTSIDE) {
              // return Intersect.OUTSIDE;
              //Modify, do not judge whether it is within the scope, and render all, so as to avoid the black box in the stereo vision part
              return Intersect.INSIDE;
          } else if (result === Intersect.INTERSECTING) {
              intersecting = true;
      return intersecting ? Intersect.INTERSECTING : Intersect.INSIDE;

Problems to be solved

After the camera is offset (left screen), the scene (left screen) should be re rendered. Specifically

    1. Judge the relationship between the boundingVolume and the CullingVolume again (INSIDE or OUTSIDE), that is, judge whether the sphere is within the camera's field of view, and render the parts within the range;
    2. Render the scene again, so as to render the slices in the current camera field of view, and avoid the appearance of black boxes

Posted by happypete on Mon, 04 May 2020 06:20:19 -0700