You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

three.js/WebVR Cardboard环境下相机沿视线持续前进实现问题

解决WebVR(Cardboard)中相机沿视线持续移动的问题

嘿,我之前在做Cardboard的three.js项目时也踩过这个一模一样的坑!非VR环境里直接改camera.position的方法在WebVR里完全失效,核心原因确实是VR系统会每一帧覆盖相机的姿态数据,直接操作相机本身根本留不住修改。下面给你一套亲测有效的解决方案:

核心思路:用「相机容器」间接控制移动

WebVR中,three.js会根据头显的实时姿态,直接更新相机的位置和朝向(也就是matrixWorld矩阵),所以我们不能直接动相机,而是把相机放到一个Object3D容器里,移动这个容器来实现整体前进:

  1. 创建相机容器并挂载相机
// 先创建你的透视相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

// 创建一个空的容器作为相机的"载体"
const cameraRig = new THREE.Object3D();
scene.add(cameraRig);
// 把相机放到容器里
cameraRig.add(camera);
  1. 在动画循环中沿视线移动容器
    在每一帧里,先获取相机当前的视线方向,再让容器沿着这个方向缓慢移动:
function animate() {
  requestAnimationFrame(animate);

  // 获取相机的世界空间前方向(three.js默认-z为前方,所以要取反)
  const forwardDir = new THREE.Vector3();
  camera.getWorldDirection(forwardDir);
  forwardDir.multiplyScalar(0.01); // 这里的数值控制移动速度,根据需求调整

  // 让容器沿着视线方向移动
  cameraRig.position.add(forwardDir);

  // 处理VR渲染(如果是新版three.js用XR,旧版用WebVR API)
  if (renderer.xr.isPresenting) {
    renderer.render(scene, camera);
  } else {
    renderer.render(scene, camera);
  }
}

为什么之前的方法没用?

在WebVR模式下,three.js的XR系统(或旧版WebVRManager)会在每一帧渲染前,根据头显的传感器数据强制更新相机的位置和朝向,你直接修改camera.position的操作会被瞬间覆盖,所以看起来相机完全没动。而用容器的话,VR系统只控制相机相对于容器的姿态(也就是你的头部转动),容器的全局位置完全由你掌控,两者互不干扰。

额外注意事项

  • 如果你用的是较新的three.js版本,确保已经启用XR:renderer.xr.enabled = true;,并正确初始化Cardboard的XR会话
  • 移动速度的数值要调得小一点,不然Cardboard里会很容易晕动
  • 测试时记得在支持WebVR/XR的浏览器中打开(比如移动端Chrome、桌面端Chrome搭配Cardboard模拟器)

内容的提问来源于stack exchange,提问作者Octavector

火山引擎 最新活动