问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Three.js正交相机:从零开始玩转3D世界

创作时间:
作者:
@小白创作中心

Three.js正交相机:从零开始玩转3D世界

在Three.js中,正交相机(OrthographicCamera)是一种特殊的相机类型,它不会产生近大远小的透视效果,而是保持物体的原始大小和形状。这种特性使得正交相机非常适合用于2D游戏开发、UI界面渲染以及各种需要等距投影的场景。

一、创建正交相机

正交相机的创建需要指定6个参数:left、right、top、bottom、near和far。这些参数定义了相机的视景体(Viewing Volume),即相机能够看到的空间范围。

const camera = new THREE.OrthographicCamera(
  left,    // 视景体左侧边界
  right,   // 视景体右侧边界
  top,     // 视景体顶部边界
  bottom,  // 视景体底部边界
  near,    // 近剪切面(必须大于0)
  far      // 远剪切面(必须大于near)
);

二、基础示例

下面是一个创建正交相机的基本示例,包括场景和渲染器的初始化:

// 创建场景
const scene = new THREE.Scene();

// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 计算视景体参数
const aspect = window.innerWidth / window.innerHeight;
const viewSize = 100; // 视景体高度

const left = -viewSize * aspect / 2;
const right = viewSize * aspect / 2;
const top = viewSize / 2;
const bottom = -viewSize / 2;
const near = 0.1;
const far = 1000;

// 创建正交相机
const camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far);
camera.position.set(0, 0, 50); // 沿z轴后移
camera.lookAt(0, 0, 0);        // 看向原点

三、动态调整相机

为了确保相机视景体与窗口大小保持一致,我们需要监听窗口的resize事件,并在窗口大小变化时更新相机的参数:

window.addEventListener('resize', () => {
  const newAspect = window.innerWidth / window.innerHeight;
  
  // 更新相机参数
  camera.left = -viewSize * newAspect / 2;
  camera.right = viewSize * newAspect / 2;
  camera.top = viewSize / 2;
  camera.bottom = -viewSize / 2;
  camera.updateProjectionMatrix(); // 必须调用!

  renderer.setSize(window.innerWidth, window.innerHeight);
});

四、应用场景

1. 2D游戏开发

在2D游戏中,我们通常希望使用像素坐标系,即原点位于左下角:

const width = 800;
const height = 600;
const camera = new THREE.OrthographicCamera(
  0,       // left
  width,   // right
  height,  // top
  0,       // bottom
  0.1, 
  1000
);
camera.position.set(width/2, height/2, 50); // 居中

2. CAD等轴测视图

在CAD软件中,我们可能需要创建等轴测视图:

camera.rotation.order = 'YXZ'; 
camera.rotation.y = Math.PI / 4; // 绕Y轴旋转45度
camera.rotation.x = Math.atan(-1 / Math.sqrt(2)); // 35.264°等轴测角

五、与透视相机的对比

特性
正交相机
透视相机
投影方式
平行投影
中心投影(模拟人眼)
参数
left/right/top/bottom/near/far
fov/aspect/near/far
应用场景
2D界面、工程制图
3D游戏、真实感渲染
物体大小
与距离无关
随距离减小

六、常见问题

  1. 物体不可见

    • 检查物体是否在near/far范围内;
    • 确认相机位置(默认在原点,可能需要camera.position.z = 50)。
  2. 图像拉伸

    • 确保left/righttop/bottom的比例匹配窗口宽高比。

七、完整代码示例

<!DOCTYPE html>
<html>
<head>
  <style> body { margin: 0; } </style>
</head>
<body>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
  <script>
    // 初始化场景、相机、渲染器
    const scene = new THREE.Scene();
    const camera = initOrthoCamera();
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 创建立方体
    const geometry = new THREE.BoxGeometry(10, 10, 10);
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 渲染循环
    function animate() {
      requestAnimationFrame(animate);
      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;
      renderer.render(scene, camera);
    }
    animate();

    // 正交相机初始化函数
    function initOrthoCamera() {
      const aspect = window.innerWidth / window.innerHeight;
      const viewSize = 100;
      const camera = new THREE.OrthographicCamera(
        -viewSize * aspect / 2,
        viewSize * aspect / 2,
        viewSize / 2,
        -viewSize / 2,
        1,
        200
      );
      camera.position.set(0, 0, 150);
      camera.lookAt(0, 0, 0);
      return camera;
    }

    // 窗口自适应
    window.addEventListener('resize', () => {
      const aspect = window.innerWidth / window.innerHeight;
      camera.left = -viewSize * aspect / 2;
      camera.right = viewSize * aspect / 2;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });
  </script>
</body>
</html>

通过以上步骤,你已经掌握了在Three.js中创建和使用正交相机的基本方法。无论是开发2D游戏还是制作工程制图,正交相机都能为你提供强大的支持。现在,不妨动手尝试一下,看看你能创造出怎样的精彩作品!

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号