Files
english/.opencode/skills/threejs/references/04-cameras.md
2026-04-12 01:06:31 +07:00

4.8 KiB

Cameras

Define viewpoint and projection for rendering.

Perspective Camera

Realistic camera with field of view (most common):

const camera = new THREE.PerspectiveCamera(
  fov,    // field of view in degrees (typically 45-75)
  aspect, // width / height
  near,   // near clipping plane (typically 0.1)
  far     // far clipping plane (typically 1000)
);

camera.position.set(0, 5, 10);
camera.lookAt(0, 0, 0);

// Update after changing parameters
camera.fov = 60;
camera.updateProjectionMatrix();

Orthographic Camera

No perspective distortion (parallel projection):

const frustumSize = 10;
const aspect = window.innerWidth / window.innerHeight;
const camera = new THREE.OrthographicCamera(
  frustumSize * aspect / -2, // left
  frustumSize * aspect / 2,  // right
  frustumSize / 2,           // top
  frustumSize / -2,          // bottom
  0.1,                       // near
  1000                       // far
);

// Useful for: 2D games, CAD, isometric views

Camera Controls (Addons)

OrbitControls (Most Common)

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

const controls = new OrbitControls(camera, renderer.domElement);
controls.target.set(0, 0, 0);
controls.enableDamping = true;   // smooth motion
controls.dampingFactor = 0.05;
controls.minDistance = 5;
controls.maxDistance = 50;
controls.maxPolarAngle = Math.PI / 2; // prevent going below ground

// In animation loop
function animate() {
  controls.update(); // required if enableDamping = true
  renderer.render(scene, camera);
}

FirstPersonControls

import { FirstPersonControls } from 'three/addons/controls/FirstPersonControls.js';

const controls = new FirstPersonControls(camera, renderer.domElement);
controls.movementSpeed = 10;
controls.lookSpeed = 0.1;

const clock = new THREE.Clock();
function animate() {
  const delta = clock.getDelta();
  controls.update(delta);
  renderer.render(scene, camera);
}

FlyControls

import { FlyControls } from 'three/addons/controls/FlyControls.js';

const controls = new FlyControls(camera, renderer.domElement);
controls.movementSpeed = 10;
controls.rollSpeed = Math.PI / 24;
controls.dragToLook = true;

TransformControls

import { TransformControls } from 'three/addons/controls/TransformControls.js';

const controls = new TransformControls(camera, renderer.domElement);
controls.attach(mesh);
scene.add(controls);

// Switch modes
controls.setMode('translate'); // or 'rotate', 'scale'

// Events
controls.addEventListener('change', () => renderer.render(scene, camera));
controls.addEventListener('dragging-changed', (event) => {
  orbitControls.enabled = !event.value;
});

Camera Methods

// Position and orientation
camera.position.set(x, y, z);
camera.lookAt(x, y, z); // or lookAt(vector3) or lookAt(object.position)
camera.up.set(0, 1, 0); // define "up" direction

// Get world direction
const direction = new THREE.Vector3();
camera.getWorldDirection(direction);

// Screen to world conversion
const mouse = new THREE.Vector2(x, y); // normalized device coords (-1 to 1)
const raycaster = new THREE.Raycaster();
raycaster.setFromCamera(mouse, camera);

// World to screen
const vector = new THREE.Vector3(x, y, z);
vector.project(camera); // now in normalized device coords

Layers

Selective rendering with layers:

// Set object layers
mesh.layers.set(1);

// Set camera layers
camera.layers.enable(0); // render layer 0
camera.layers.enable(1); // render layer 1
camera.layers.disable(2); // don't render layer 2

// Objects on disabled layers won't be rendered

Frustum Culling

Automatic optimization (objects outside view are not rendered):

// Manually check if object is in view
const frustum = new THREE.Frustum();
const matrix = new THREE.Matrix4().multiplyMatrices(
  camera.projectionMatrix,
  camera.matrixWorldInverse
);
frustum.setFromProjectionMatrix(matrix);

if (frustum.containsPoint(object.position)) {
  // Object is visible
}

Multiple Cameras

const mainCamera = new THREE.PerspectiveCamera(...);
const minimapCamera = new THREE.OrthographicCamera(...);

// Render with different viewports
renderer.setViewport(0, 0, width, height);
renderer.render(scene, mainCamera);

renderer.setViewport(width - 200, height - 200, 200, 200);
renderer.render(scene, minimapCamera);

Resize Handling

window.addEventListener('resize', () => {
  // Perspective camera
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  // Orthographic camera
  const aspect = window.innerWidth / window.innerHeight;
  camera.left = -frustumSize * aspect / 2;
  camera.right = frustumSize * aspect / 2;
  camera.updateProjectionMatrix();

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