使用THREE.js和WebVR的VR倒置跟踪和不正确的相机分隔

时间:2018-10-03 17:49:25

标签: three.js webvr

我一直在尝试将找到的here的THREE.js WebGL转换为THREE.js WebVR,以使其具有VR兼容性。我修改了main.js文件以使用某些功能,并添加了相关的javascript库库。

但是,在测试VR功能时,我注意到了两个主要问题。首先是VR跟踪控件被颠倒了。换句话说,如果我抬头,相机就往下看。如果我向左看,相机向右看,反之亦然。

另一个问题是图像看起来相距太远。当我使用VR头戴式耳机时,会看到两个单独的图像,而不是一个整体的图像。

我想知道是否有人知道导致这些问题的原因以及如何解决这些问题。我怀疑问题与原始代码中存在的一些复杂旋转有关,这些旋转未正确转换为VR。一般来说,这是我第一次使用VR或THREE.js,因此不胜感激。

我认为这是代码的相关部分:

"use strict"
/*global THREE, SHADER_LOADER, Mustache, Stats, Detector, $, dat:false */
/*global document, window, setTimeout, requestAnimationFrame:false */
/*global ProceduralTextures:false */

if (!Detector.webgl) Detector.addGetWebGLMessage();

function Observer() {
  this.position = new THREE.Vector3(10, 0, 0);
  this.velocity = new THREE.Vector3(0, 1, 0);
  this.orientation = new THREE.Matrix3();
  this.time = 0.0;
}

Observer.prototype.orbitalFrame = function() {

  //var orbital_y = observer.velocity.clone().normalize();
  var orbital_y = (new THREE.Vector3())
    .subVectors(observer.velocity.clone().normalize().multiplyScalar(4.0),
      observer.position).normalize();

  var orbital_z = (new THREE.Vector3())
    .crossVectors(observer.position, orbital_y).normalize();
  var orbital_x = (new THREE.Vector3()).crossVectors(orbital_y, orbital_z);


  return (new THREE.Matrix4()).makeBasis(
    orbital_x,
    orbital_y,
    orbital_z
  ).linearPart();
};

Observer.prototype.move = function(dt) {

  dt *= shader.parameters.time_scale;

  var r;
  var v = 0;

  // motion on a pre-defined cirular orbit
  if (shader.parameters.observer.motion) {

    r = shader.parameters.observer.distance;
    v = 1.0 / Math.sqrt(2.0 * (r - 1.0));
    var ang_vel = v / r;
    var angle = this.time * ang_vel;

    var s = Math.sin(angle),
      c = Math.cos(angle);

    this.position.set(c * r, s * r, 0);
    this.velocity.set(-s * v, c * v, 0);

    var alpha = degToRad(shader.parameters.observer.orbital_inclination);
    var orbit_coords = (new THREE.Matrix4()).makeRotationY(alpha);

    this.position.applyMatrix4(orbit_coords);
    this.velocity.applyMatrix4(orbit_coords);
  } else {
    r = this.position.length();
  }

  if (shader.parameters.gravitational_time_dilation) {
    dt = Math.sqrt((dt * dt * (1.0 - v * v)) / (1 - 1.0 / r));
  }

  this.time += dt;
};

var container, stats;
var camera, scene, renderer, cameraControls, shader, dollycam;
var observer = new Observer();

...

var updateUniforms;

function init(textures) {

  container = document.createElement('div');
  document.body.appendChild(container);

  scene = new THREE.Scene();

  var geometry = new THREE.PlaneBufferGeometry(2, 2);

  var uniforms = {
    time: {
      type: "f",
      value: 0
    },
    resolution: {
      type: "v2",
      value: new THREE.Vector2()
    },
    cam_pos: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_x: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_y: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_z: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_vel: {
      type: "v3",
      value: new THREE.Vector3()
    },

    planet_distance: {
      type: "f"
    },
    planet_radius: {
      type: "f"
    },

    star_texture: {
      type: "t",
      value: textures.stars
    },
    accretion_disk_texture: {
      type: "t",
      value: textures.accretion_disk
    },
    galaxy_texture: {
      type: "t",
      value: textures.galaxy
    },
    planet_texture: {
      type: "t",
      value: textures.moon
    },
    spectrum_texture: {
      type: "t",
      value: textures.spectra
    }
  };

  updateUniforms = function() {
    uniforms.planet_distance.value = shader.parameters.planet.distance;
    uniforms.planet_radius.value = shader.parameters.planet.radius;

    uniforms.resolution.value.x = renderer.domElement.width;
    uniforms.resolution.value.y = renderer.domElement.height;

    uniforms.time.value = observer.time;
    uniforms.cam_pos.value = observer.position;

    var e = observer.orientation.elements;

    uniforms.cam_x.value.set(e[0], e[1], e[2]);
    uniforms.cam_y.value.set(e[3], e[4], e[5]);
    uniforms.cam_z.value.set(e[6], e[7], e[8]);

    function setVec(target, value) {
      uniforms[target].value.set(value.x, value.y, value.z);
    }

    setVec('cam_pos', observer.position);
    setVec('cam_vel', observer.velocity);
  };

  var material = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: $('#vertex-shader').text(),
  });

  scene.updateShader = function() {
    material.fragmentShader = shader.compile();
    material.needsUpdate = true;
    shader.needsUpdate = true;
  };

  scene.updateShader();

  var mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.vr.enabled = true; // added vr
  document.body.appendChild(renderer.domElement);
  document.body.appendChild(WEBVR.createButton(renderer));
  // renderer.autoClear = false;  


  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.top = '0px';
  container.appendChild(stats.domElement);
  $(stats.domElement).addClass('hidden-phone');

  // Orbit camera from three.js
  camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 80000);
  // initializeCamera(camera);
  //initiallize camera
  var pitchAngle = 3.0,
    yawAngle = 0.0;

  // there are nicely named methods such as "lookAt" in the camera object
  // but there do not do a thing to the projection matrix due to an internal
  // representation of the camera coordinates using a quaternion (nice)
  camera.matrixWorldInverse.makeRotationX(degToRad(-pitchAngle));
  camera.matrixWorldInverse.multiply(new THREE.Matrix4().makeRotationY(degToRad(-yawAngle)));

  var m = camera.matrixWorldInverse.elements;
  dollycam = new THREE.PerspectiveCamera();
  dollycam.position.set(m[2], m[6], m[10]);
  // camera.position.set(m[2],m[6],m[10]);


  dollycam.add(camera);
  scene.add(dollycam);

  cameraControls = new THREE.OrbitControls(dollycam, renderer.domElement);

  // cameraControls.target.set( 0, 0, 0 );
  cameraControls.addEventListener('change', updateCamera);
  cameraControls.update()
  updateCamera();

  onWindowResize();

  window.addEventListener('resize', onWindowResize, false);

  setupGUI();
}
...

function onWindowResize(event) {
  renderer.setSize(window.innerWidth, window.innerHeight);
  updateUniforms();
}

function updateCamera(event) {

  var zoom_dist = camera.position.length();
  var m = camera.matrixWorldInverse.elements;
  var camera_matrix;

  if (shader.parameters.observer.motion) {
    camera_matrix = new THREE.Matrix3();
  } else {
    camera_matrix = observer.orientation;
  }

  camera_matrix.set(
    // row-major, not the same as .elements (nice)
    // y and z swapped for a nicer coordinate system
    m[0], m[1], m[2],
    m[8], m[9], m[10],
    m[4], m[5], m[6]
  );

  observer.orientation = observer.orbitalFrame().multiply(camera_matrix);

}

..

function animate() {
  // requestAnimationFrame( animate );

  // renderer.setAnimationLoop(     renderer.render( scene, camera )   );
  renderer.setAnimationLoop(render);

}

var lastCameraMat = new THREE.Matrix4().identity();

var getFrameDuration = (function() {
  var lastTimestamp = new Date().getTime();
  return function() {
    var timestamp = new Date().getTime();
    var diff = (timestamp - lastTimestamp) / 1000.0;
    lastTimestamp = timestamp;
    return diff;
  };
})();

function render() {
  // renderer.render( scene, camera );
  camera.updateMatrixWorld();
  camera.matrixWorldInverse.getInverse(camera.matrixWorld);
  // dollycam.updateMatrixWorld();
  // dollycam.matrixWorldInverse.getInverse( dollycam.matrixWorld );
  updateCamera();

  if (shader.needsUpdate || shader.hasMovingParts() ||
    frobeniusDistance(camera.matrixWorldInverse, lastCameraMat) > 1e-10) {

    shader.needsUpdate = false;
    observer.move(getFrameDuration());
    cameraControls.update();
    updateCamera();
    updateUniforms();

    // render();
    renderer.render(scene, camera);
    lastCameraMat = camera.matrixWorldInverse.clone();

    stats.update();

  }

这是完整的代码:

"use strict"
/*global THREE, SHADER_LOADER, Mustache, Stats, Detector, $, dat:false */
/*global document, window, setTimeout, requestAnimationFrame:false */
/*global ProceduralTextures:false */

if (!Detector.webgl) Detector.addGetWebGLMessage();

function Observer() {
  this.position = new THREE.Vector3(10, 0, 0);
  this.velocity = new THREE.Vector3(0, 1, 0);
  this.orientation = new THREE.Matrix3();
  this.time = 0.0;
}

Observer.prototype.orbitalFrame = function() {

  //var orbital_y = observer.velocity.clone().normalize();
  var orbital_y = (new THREE.Vector3())
    .subVectors(observer.velocity.clone().normalize().multiplyScalar(4.0),
      observer.position).normalize();

  var orbital_z = (new THREE.Vector3())
    .crossVectors(observer.position, orbital_y).normalize();
  var orbital_x = (new THREE.Vector3()).crossVectors(orbital_y, orbital_z);


  return (new THREE.Matrix4()).makeBasis(
    orbital_x,
    orbital_y,
    orbital_z
  ).linearPart();
};

Observer.prototype.move = function(dt) {

  dt *= shader.parameters.time_scale;

  var r;
  var v = 0;

  // motion on a pre-defined cirular orbit
  if (shader.parameters.observer.motion) {

    r = shader.parameters.observer.distance;
    v = 1.0 / Math.sqrt(2.0 * (r - 1.0));
    var ang_vel = v / r;
    var angle = this.time * ang_vel;

    var s = Math.sin(angle),
      c = Math.cos(angle);

    this.position.set(c * r, s * r, 0);
    this.velocity.set(-s * v, c * v, 0);

    var alpha = degToRad(shader.parameters.observer.orbital_inclination);
    var orbit_coords = (new THREE.Matrix4()).makeRotationY(alpha);

    this.position.applyMatrix4(orbit_coords);
    this.velocity.applyMatrix4(orbit_coords);
  } else {
    r = this.position.length();
  }

  if (shader.parameters.gravitational_time_dilation) {
    dt = Math.sqrt((dt * dt * (1.0 - v * v)) / (1 - 1.0 / r));
  }

  this.time += dt;
};

var container, stats;
var camera, scene, renderer, cameraControls, shader, dollycam;
var observer = new Observer();



function Shader(mustacheTemplate) {
  // Compile-time shader parameters
  this.parameters = {
    n_steps: 100,
    quality: 'medium',
    accretion_disk: true,
    planet: {
      enabled: true,
      distance: 4.0,
      radius: 0.5
    },
    lorentz_contraction: true,
    gravitational_time_dilation: true,
    aberration: true,
    beaming: true,
    doppler_shift: true,
    light_travel_time: true,
    time_scale: 1.0,
    observer: {
      motion: true,
      distance: 7.0,
      orbital_inclination: -10
    },

    planetEnabled: function() {
      return this.planet.enabled && this.quality !== 'fast';
    },

    observerMotion: function() {
      return this.observer.motion;
    }
  };
  var that = this;
  this.needsUpdate = false;

  this.hasMovingParts = function() {
    return this.parameters.planet.enabled || this.parameters.observer.motion;
  };

  this.compile = function() {
    return Mustache.render(mustacheTemplate, that.parameters);
  };
}

function degToRad(a) {
  return Math.PI * a / 180.0;
}

(function() {
  var textures = {};

  function whenLoaded() {
    init(textures);
    $('#loader').hide();
    $('.initially-hidden').removeClass('initially-hidden');
    animate();
  }

  function checkLoaded() {
    if (shader === null) return;
    for (var key in textures)
      if (textures[key] === null) return;
    whenLoaded();
  }

  SHADER_LOADER.load(function(shaders) {
    shader = new Shader(shaders.raytracer.fragment);
    checkLoaded();
  });

  var texLoader = new THREE.TextureLoader();

  function loadTexture(symbol, filename, interpolation) {
    textures[symbol] = null;
    texLoader.load(filename, function(tex) {
      tex.magFilter = interpolation;
      tex.minFilter = interpolation;
      textures[symbol] = tex;
      checkLoaded();
    });
  }

  loadTexture('galaxy', 'img/milkyway.jpg', THREE.NearestFilter);
  loadTexture('spectra', 'img/spectra.png', THREE.LinearFilter);
  loadTexture('moon', 'img/beach-ball.png', THREE.LinearFilter);
  loadTexture('stars', 'img/stars.png', THREE.LinearFilter);
  loadTexture('accretion_disk', 'img/accretion-disk.png', THREE.LinearFilter);
})();

var updateUniforms;

function init(textures) {

  container = document.createElement('div');
  document.body.appendChild(container);

  scene = new THREE.Scene();

  var geometry = new THREE.PlaneBufferGeometry(2, 2);

  var uniforms = {
    time: {
      type: "f",
      value: 0
    },
    resolution: {
      type: "v2",
      value: new THREE.Vector2()
    },
    cam_pos: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_x: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_y: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_z: {
      type: "v3",
      value: new THREE.Vector3()
    },
    cam_vel: {
      type: "v3",
      value: new THREE.Vector3()
    },

    planet_distance: {
      type: "f"
    },
    planet_radius: {
      type: "f"
    },

    star_texture: {
      type: "t",
      value: textures.stars
    },
    accretion_disk_texture: {
      type: "t",
      value: textures.accretion_disk
    },
    galaxy_texture: {
      type: "t",
      value: textures.galaxy
    },
    planet_texture: {
      type: "t",
      value: textures.moon
    },
    spectrum_texture: {
      type: "t",
      value: textures.spectra
    }
  };

  updateUniforms = function() {
    uniforms.planet_distance.value = shader.parameters.planet.distance;
    uniforms.planet_radius.value = shader.parameters.planet.radius;

    uniforms.resolution.value.x = renderer.domElement.width;
    uniforms.resolution.value.y = renderer.domElement.height;

    uniforms.time.value = observer.time;
    uniforms.cam_pos.value = observer.position;

    var e = observer.orientation.elements;

    uniforms.cam_x.value.set(e[0], e[1], e[2]);
    uniforms.cam_y.value.set(e[3], e[4], e[5]);
    uniforms.cam_z.value.set(e[6], e[7], e[8]);

    function setVec(target, value) {
      uniforms[target].value.set(value.x, value.y, value.z);
    }

    setVec('cam_pos', observer.position);
    setVec('cam_vel', observer.velocity);
  };

  var material = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: $('#vertex-shader').text(),
  });

  scene.updateShader = function() {
    material.fragmentShader = shader.compile();
    material.needsUpdate = true;
    shader.needsUpdate = true;
  };

  scene.updateShader();

  var mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  renderer = new THREE.WebGLRenderer();
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.vr.enabled = true; // added vr
  document.body.appendChild(renderer.domElement);
  document.body.appendChild(WEBVR.createButton(renderer));
  // renderer.autoClear = false;  


  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.top = '0px';
  container.appendChild(stats.domElement);
  $(stats.domElement).addClass('hidden-phone');

  // Orbit camera from three.js
  camera = new THREE.PerspectiveCamera(80, window.innerWidth / window.innerHeight, 1, 80000);
  // initializeCamera(camera);
  //initiallize camera
  var pitchAngle = 3.0,
    yawAngle = 0.0;

  // there are nicely named methods such as "lookAt" in the camera object
  // but there do not do a thing to the projection matrix due to an internal
  // representation of the camera coordinates using a quaternion (nice)
  camera.matrixWorldInverse.makeRotationX(degToRad(-pitchAngle));
  camera.matrixWorldInverse.multiply(new THREE.Matrix4().makeRotationY(degToRad(-yawAngle)));

  var m = camera.matrixWorldInverse.elements;
  dollycam = new THREE.PerspectiveCamera();
  dollycam.position.set(m[2], m[6], m[10]);
  // camera.position.set(m[2],m[6],m[10]);


  dollycam.add(camera);
  scene.add(dollycam);

  cameraControls = new THREE.OrbitControls(dollycam, renderer.domElement);

  // cameraControls.target.set( 0, 0, 0 );
  cameraControls.addEventListener('change', updateCamera);
  cameraControls.update()
  updateCamera();

  onWindowResize();

  window.addEventListener('resize', onWindowResize, false);

  setupGUI();
}

function setupGUI() {

  var hint = $('#hint-text');
  var p = shader.parameters;

  function updateShader() {
    hint.hide();
    scene.updateShader();
  }

  var gui = new dat.GUI();

  gui.add(p, 'quality', ['fast', 'medium', 'high']).onChange(function(value) {
    $('.planet-controls').show();
    switch (value) {
      case 'fast':
        p.n_steps = 40;
        $('.planet-controls').hide();
        break;
      case 'medium':
        p.n_steps = 100;
        break;
      case 'high':
        p.n_steps = 200;
        break;
    }

    updateShader();
  });
  gui.add(p, 'accretion_disk').onChange(updateShader);

  var folder = gui.addFolder('Observer');
  folder.add(p.observer, 'motion').onChange(function(motion) {
    updateCamera();
    updateShader();
    if (motion) {
      hint.text('Moving observer; drag to rotate camera');
    } else {
      hint.text('Stationary observer; drag to orbit around');
    }
    hint.fadeIn();
  });
  folder.add(p.observer, 'distance').min(1.5).max(30).onChange(updateCamera);
  folder.open();

  folder = gui.addFolder('Planet');
  folder.add(p.planet, 'enabled').onChange(function(enabled) {
    updateShader();
    var controls = $('.indirect-planet-controls').show();
    if (enabled) controls.show();
    else controls.hide();
  });
  folder.add(p.planet, 'distance').min(1.5).onChange(updateUniforms);
  folder.add(p.planet, 'radius').min(0.01).max(2.0).onChange(updateUniforms);
  $(folder.domElement).addClass('planet-controls');
  //folder.open();

  function setGuiRowClass(guiEl, klass) {
    $(guiEl.domElement).parent().parent().addClass(klass);
  }

  folder = gui.addFolder('Relativistic effects');
  folder.add(p, 'aberration').onChange(updateShader);
  folder.add(p, 'beaming').onChange(updateShader);
  folder.add(p, 'doppler_shift').onChange(updateShader);
  setGuiRowClass(
    folder.add(p, 'gravitational_time_dilation').onChange(updateShader),
    'planet-controls indirect-planet-controls');
  setGuiRowClass(
    folder.add(p, 'lorentz_contraction').onChange(updateShader),
    'planet-controls indirect-planet-controls');

  folder.open();

  folder = gui.addFolder('Time');
  folder.add(p, 'light_travel_time').onChange(updateShader);
  folder.add(p, 'time_scale').min(0);
  //folder.open();

}

function onWindowResize(event) {
  renderer.setSize(window.innerWidth, window.innerHeight);
  updateUniforms();
}



function updateCamera(event) {

  var zoom_dist = camera.position.length();
  var m = camera.matrixWorldInverse.elements;
  var camera_matrix;

  if (shader.parameters.observer.motion) {
    camera_matrix = new THREE.Matrix3();
  } else {
    camera_matrix = observer.orientation;
  }

  camera_matrix.set(
    // row-major, not the same as .elements (nice)
    // y and z swapped for a nicer coordinate system
    m[0], m[1], m[2],
    m[8], m[9], m[10],
    m[4], m[5], m[6]
  );

  // if (shader.parameters.observer.motion) {

  observer.orientation = observer.orbitalFrame().multiply(camera_matrix);

  // } else {

  //     var p = new THREE.Vector3(
  //         camera_matrix.elements[6],
  //         camera_matrix.elements[7],
  //         camera_matrix.elements[8]);

  //     var dist = shader.parameters.observer.distance;
  //     observer.position.set(-p.x*dist, -p.y*dist, -p.z*dist);
  //     observer.velocity.set(0,0,0);
  // }
}

function frobeniusDistance(matrix1, matrix2) {
  var sum = 0.0;
  for (var i in matrix1.elements) {
    var diff = matrix1.elements[i] - matrix2.elements[i];
    sum += diff * diff;
  }
  return Math.sqrt(sum);
}

function animate() {
  // requestAnimationFrame( animate );

  // renderer.setAnimationLoop(     renderer.render( scene, camera )   );
  renderer.setAnimationLoop(render);

}

var lastCameraMat = new THREE.Matrix4().identity();

var getFrameDuration = (function() {
  var lastTimestamp = new Date().getTime();
  return function() {
    var timestamp = new Date().getTime();
    var diff = (timestamp - lastTimestamp) / 1000.0;
    lastTimestamp = timestamp;
    return diff;
  };
})();

function render() {
  // renderer.render( scene, camera );
  camera.updateMatrixWorld();
  camera.matrixWorldInverse.getInverse(camera.matrixWorld);
  // dollycam.updateMatrixWorld();
  // dollycam.matrixWorldInverse.getInverse( dollycam.matrixWorld );
  updateCamera();

  if (shader.needsUpdate || shader.hasMovingParts() ||
    frobeniusDistance(camera.matrixWorldInverse, lastCameraMat) > 1e-10) {

    shader.needsUpdate = false;
    observer.move(getFrameDuration());
    cameraControls.update();
    updateCamera();
    updateUniforms();

    // render();
    renderer.render(scene, camera);
    lastCameraMat = camera.matrixWorldInverse.clone();
  }
  stats.update();

}
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Black Hole</title>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
        <meta property="og:url"                content="https://oseiskar.github.io/black-hole" />
        <meta property="og:title"              content="THREE.js Black Hole" />
        <meta property="og:description"        content="A real time ray-traced simulation of a Schwarzschild black hole. Needs a decent GPU and a recent variant of Chrome or Firefox to run smoothly." />
        <meta property="og:image"              content="http://oseiskar.github.io/img/black-hole.jpg" />
        <link rel="stylesheet" href="style.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!DOCTYPE html>
<html lang="en">
    <head>
        <div id="hint-text" class="hidden-phone initially-hidden">
            <!-- Drag to rotate or toggle variables on the right ⟶ -->
        </div>
        <div class="info ">
            <div id="loader">
                Loading...
                <div class="disclaimer">
                
                </div>
            </div>

        </div>

        <!-- <div class="link-bar">
            <a href="README" target="_blank"><i class="fa fa-question-circle fa-lg"></i> What is this?</a>
            |
            <a href="https://github.com/oseiskar/black-hole" target="_blank"><i class="fa fa-github fa-lg"></i> Source</a>
            |
            <a href="docs/physics.html" target="_blank"><i class="fa fa-lg">&Sigma;</i> Physics</a>
            |
        </div> -->

        <script src="js-libs/jquery-2.1.4.min.js"></script>
        <!-- <script src="js-libs/three.min.js"></script> -->
        <script src="js-libs/three.js"></script>
        <script src="js-libs/WebVR.js"></script>
        <!-- <script src="js-libs/VRControls.js"></script> -->
        <!-- <script src="js-libs/VREffect.js"></script> -->
        <script src="js-libs/OrbitControls.js"></script>
        <script src="js-libs/Detector.js"></script>
        <!-- <script src="js-libs/DeviceOrientationControls.js"></script> -->
        <script src="js-libs/stats.min.js"></script>
        <script src="js-libs/ShaderLoader.min.js"></script>
        <script src="js-libs/mustache.min.js"></script>
        <script src="js-libs/dat.gui.min.js"></script>
        <script src="three-js-monkey-patch.js"></script>
        <!-- <script src="js-libs/webvr-polyfill.js"></script> -->
        <!-- <script src="js-libs/webvr-manager.js"></script> -->
        

        <script id="vertex-shader" type="x-shader/x-vertex">

            void main()    {

                gl_Position = vec4( position, 1.0 );

            }

        </script>
        <script data-src="raytracer.glsl" data-name="raytracer" type="x-shader/x-fragment"></script>
        <script src="main.js"></script>

    </body>
</html>

编辑1:我解决了更换倒置摄像头的问题 function updateCamera(event) { var zoom_dist = camera.position.length(); var m = camera.matrixWorldInverse.elements; var camera_matrix;function updateCamera(event) { var zoom_dist = camera.position.length(); var m = camera.matrixWorld.elements; var camera_matrix; 我的显示器仍然有问题。看起来,VR模式下的显示呈现为单个连续图像,而不是两个稍微偏移的立体图像。

0 个答案:

没有答案