Three.js - PerspectiveCamera
Three.js 中有不同的相机。最常见的相机和我们一直在使用的相机是 PerspectiveCamera。
const camera = new THREE.PerspectiveCamera(fov, aspects, near, far)
第一个属性是视场 (FOV)。FOV 是场景中在任何给定时刻在显示屏上可见的部分。该值以度为单位。人类的视场几乎为 180 度。但由于普通电脑屏幕无法填满我们的视野,因此通常会选择较小的值。一般来说,对于游戏来说,FOV 最好在 60 到 90 度之间。
良好的默认值:50
第二个是纵横比 - 我们正在渲染输出的区域的水平和垂直大小之间的比率。
良好的默认值:window.innerWidth / window.innerHeight
以下两个属性是近裁剪平面和远裁剪平面。相机在屏幕上渲染近平面和远平面之间的区域。
near 属性定义 Three.js 应将场景渲染到离相机多近的位置。通常,我们将其设置为最小值,以便直接从相机的位置渲染所有内容。
良好的默认值:0.1
far 属性定义相机从相机位置可以看到多远。如果我们将其设置得太低,场景的一部分可能无法渲染,如果我们将其设置得太高,在某些情况下,它可能会影响渲染性能。
良好的默认值:1000

示例
查看以下示例并尝试使用变量。
prespective-cam.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Three.js - Prespective camera</title> <style> html, body { margin: 0; height: 100%; } #threejs-container { width: 100%; height: 100%; display: block; } .split { position: absolute; left: 0; top: 0; width: 100%; height: 100%; display: flex; } .split > div { width: 100%; height: 100%; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.js"></script> </head> <body> <canvas id="threejs-container"></canvas> <div class="split"> <div id="view1" tabindex="1"></div> <div id="view2" tabindex="2"></div> </div> <script type="module"> // Three.js - Cameras - Prespective 2 views // from https://threejsfundamentals.org/threejs/threejs-camerasprespective-2-scenes.html import { OrbitControls } from "https://threejs.org/examples/jsm/contro ls/OrbitControls.js" function main() { const canvas = document.querySelector('#threejs-container') const view1Elem = document.querySelector('#view1') const view2Elem = document.querySelector('#view2') const renderer = new THREE.WebGLRenderer({ canvas, antialias: true }) const fov = 45 const aspect = 2 // the canvas default const near = 5 const far = 100 const camera = new THREE.PerspectiveCamera(fov, aspect, near, far) camera.position.set(0, 10, 20) const cameraHelper = new THREE.CameraHelper(camera) class MinMaxGUIHelper { constructor(obj, minProp, maxProp, minDif) { this.obj = obj this.minProp = minProp this.maxProp = maxProp this.minDif = minDif } get min() { return this.obj[this.minProp] } set min(v) { this.obj[this.minProp] = v this.obj[this.maxProp] = Math.max(this.obj[this.maxProp], v + th is.minDif) } get max() { return this.obj[this.maxProp] } set max(v) { this.obj[this.maxProp] = v this.min = this.min // this will call the min setter } } const gui = new dat.GUI() gui.add(camera, 'fov', 1, 180) const minMaxGUIHelper = new MinMaxGUIHelper(camera, 'near', 'far', 0.1) gui.add(minMaxGUIHelper, 'min', 0.1, 50, 0.1).name('near') gui.add(minMaxGUIHelper, 'max', 0.1, 50, 0.1).name('far') const controls = new OrbitControls(camera, view1Elem) controls.target.set(0, 5, 0) controls.update() const camera2 = new THREE.PerspectiveCamera( 60, // fov 2, // aspect 0.1, // near 500 // far ) camera2.position.set(40, 10, 30) camera2.lookAt(0, 5, 0) const controls2 = new OrbitControls(camera2, view2Elem) controls2.target.set(0, 5, 0) controls2.update() const scene = new THREE.Scene() scene.background = new THREE.Color(0x262626) scene.add(cameraHelper) { const planeSize = 40 const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize) const planeMat = new THREE.MeshLambertMaterial({ color: 0xffffff, side: THREE.DoubleSide }) const mesh = new THREE.Mesh(planeGeo, planeMat) mesh.rotation.x = Math.PI * -0.5 scene.add(mesh) } { const cubeSize = 4 const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize) const cubeMat = new THREE.MeshLambertMaterial({ color: 0x87ceeb }) const mesh = new THREE.Mesh(cubeGeo, cubeMat) mesh.position.set(cubeSize + 1, cubeSize / 2, 0) scene.add(mesh) } { const sphereRadius = 3 const sphereWidthDivisions = 32 const sphereHeightDivisions = 16 const sphereGeo = new THREE.SphereGeometry( sphereRadius, sphereWidthDivisions, sphereHeightDivisions ) const sphereMat = new THREE.MeshLambertMaterial({ color: 0x71ba80 }) const mesh = new THREE.Mesh(sphereGeo, sphereMat) mesh.position.set(-sphereRadius - 1, sphereRadius + 2, 0) scene.add(mesh) } { const color = 0xffffff const intensity = 1 const light = new THREE.DirectionalLight(color, intensity) light.position.set(0, 10, 5) light.target.position.set(-5, 0, 0) scene.add(light) scene.add(light.target) const light2 = new THREE.DirectionalLight(color, intensity) light2.position.set(0, 10, -5) light2.target.position.set(-5, 0, 0) scene.add(light2) scene.add(light2.target) } function resizeRendererToDisplaySize(renderer) { const canvas = renderer.domElement const width = canvas.clientWidth const height = canvas.clientHeight const needResize = canvas.width !== width || canvas.height !== height if (needResize) { renderer.setSize(width, height, false) } return needResize } function setScissorForElement(elem) { const canvasRect = canvas.getBoundingClientRect() const elemRect = elem.getBoundingClientRect() // compute a canvas relative rectangle const right = Math.min(elemRect.right, canvasRect.right) - canvasR ect.left const left = Math.max(0, elemRect.left - canvasRect.left) const bottom = Math.min(elemRect.bottom, canvasRect.bottom) - canv asRect.top const top = Math.max(0, elemRect.top - canvasRect.top) const width = Math.min(canvasRect.width, right - left) const height = Math.min(canvasRect.height, bottom - top) // setup the scissor to only render to that part of the canvas const positiveYUpBottom = canvasRect.height - bottom renderer.setScissor(left, positiveYUpBottom, width, height) renderer.setViewport(left, positiveYUpBottom, width, height) // return the aspect return width / height } function render() { resizeRendererToDisplaySize(renderer) // turn on the scissor renderer.setScissorTest(true) // render the original view { const aspect = setScissorForElement(view1Elem) // adjust the camera for this aspect camera.aspect = aspect camera.updateProjectionMatrix() cameraHelper.update() // don't draw the camera helper in the original view cameraHelper.visible = false scene.background.set(0x262626) // render renderer.render(scene, camera) } // render from the 2nd camera { const aspect = setScissorForElement(view2Elem) // adjust the camera for this aspect camera2.aspect = aspect camera2.updateProjectionMatrix() // draw the camera helper in the 2nd view cameraHelper.visible = true scene.background.set(0x262626) renderer.render(scene, camera2) } requestAnimationFrame(render) } requestAnimationFrame(render) } main() </script> </body> </html>
输出
