第二篇:Three.js核心三要素:場景、相機、渲染器
引言
在Three.js的世界里,場景(Scene)、相機(Camera)和渲染器(Renderer)構成了最基礎的"鐵三角"。它們如同導演、攝像機和放映機,共同決定了3D內容的呈現方式。本篇將深入解析這三個核心組件,并通過Vue3實戰案例展示它們的協同工作。
1. 場景(Scene):3D世界的容器
1.1 場景的本質
場景是Three.js的頂級容器,所有3D對象(網格、燈光、相機)都需要加入場景才能被渲染。可以將其理解為:
- 3D對象的舞臺
- 空間坐標系的管理者
- 場景圖(Scene Graph)的根節點
// 創建場景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // 設置天空藍背景
1.2 場景層級管理
Three.js使用樹狀結構管理對象:
實戰:使用Group組織對象
<script setup>
import { ref, onMounted } from 'vue';
import * as THREE from 'three';const scene = new THREE.Scene();// 創建汽車組
const carGroup = new THREE.Group();
scene.add(carGroup);// 車身
const bodyGeo = new THREE.BoxGeometry(2, 0.5, 1);
const bodyMat = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const body = new THREE.Mesh(bodyGeo, bodyMat);
carGroup.add(body);// 車輪
const wheelGeo = new THREE.CylinderGeometry(0.3, 0.3, 0.2, 16);
wheelGeo.rotateZ(Math.PI/2); // 旋轉90度使其立起
const wheelMat = new THREE.MeshBasicMaterial({ color: 0x333333 });const wheel1 = new THREE.Mesh(wheelGeo, wheelMat);
wheel1.position.set(0.7, -0.3, 0.5);
carGroup.add(wheel1);const wheel2 = wheel1.clone();
wheel2.position.z = -0.5;
carGroup.add(wheel2);// 移動整個汽車組
carGroup.position.x = -3;
</script>
關鍵點:
Group
允許將多個對象作為單一實體操作,大幅簡化復雜對象的變換控制。
2. 相機(Camera):觀察世界的眼睛
2.1 透視相機(PerspectiveCamera)
模擬人眼視角,近大遠小效果:
const camera = new THREE.PerspectiveCamera(75, // 視野角度(FOV)window.innerWidth / window.innerHeight, // 寬高比0.1, // 近裁剪面(near)1000 // 遠裁剪面(far)
);
camera.position.set(0, 2, 5); // 設置相機位置
2.2 正交相機(OrthographicCamera)
平行投影,無透視變形:
const aspect = window.innerWidth / window.innerHeight;
const camera = new THREE.OrthographicCamera(-5 * aspect, // left5 * aspect, // right5, // top-5, // bottom0.1, // near100 // far
);
2.3 相機類型對比
特性 | 透視相機 | 正交相機 |
---|---|---|
投影方式 | 錐形投影 | 平行投影 |
適用場景 | 真實感場景 | 技術圖紙/2.5D游戲 |
尺寸感知 | 近大遠小 | 保持物體原尺寸 |
參數復雜度 | 簡單(4參數) | 復雜(6參數) |
典型應用 | 第一人稱游戲 | CAD查看器 |
3. 渲染器(Renderer):將3D轉為2D
3.1 渲染器核心配置
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';const canvasRef = ref(null);onMounted(() => {const renderer = new THREE.WebGLRenderer({canvas: canvasRef.value,antialias: true, // 開啟抗鋸齒alpha: true, // 允許透明背景powerPreference: "high-performance" // 高性能模式});// 設置像素比和尺寸renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));renderer.setSize(window.innerWidth, window.innerHeight);// 開啟陰影renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 柔和陰影
});
</script>
3.2 響應式窗口處理
// Vue3中使用@vueuse/core監聽窗口變化
import { useWindowSize } from '@vueuse/core';const { width, height } = useWindowSize();watch([width, height], () => {camera.aspect = width.value / height.value;camera.updateProjectionMatrix(); // 必須更新相機renderer.setSize(width.value, height.value);
});
4. 綜合實戰:多相機切換系統
4.1 項目結構
src/├── components/│ ├── CameraSystem.vue // 相機系統組件│ └── SceneObjects.vue // 場景對象組件└── App.vue
4.2 相機切換核心代碼
<!-- CameraSystem.vue -->
<script setup>
import { ref } from 'vue';// 相機枚舉類型
const CameraType = {PERSPECTIVE: 0,ORTHOGRAPHIC: 1
};const currentCamera = ref(CameraType.PERSPECTIVE);
const cameras = {[CameraType.PERSPECTIVE]: createPerspectiveCamera(),[CameraType.ORTHOGRAPHIC]: createOrthographicCamera()
};function createPerspectiveCamera() {const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);camera.position.set(0, 2, 5);return camera;
}function createOrthographicCamera() {const aspect = window.innerWidth / window.innerHeight;const camera = new THREE.OrthographicCamera(-5*aspect, 5*aspect, 5, -5, 0.1, 100);camera.position.set(0, 2, 5);camera.lookAt(0, 0, 0);return camera;
}function toggleCamera() {currentCamera.value = currentCamera.value === CameraType.PERSPECTIVE ? CameraType.ORTHOGRAPHIC : CameraType.PERSPECTIVE;
}
</script><template><button @click="toggleCamera" class="camera-toggle">{{ currentCamera === CameraType.PERSPECTIVE ? '正交視圖' : '透視視圖' }}</button>
</template>
4.3 渲染循環適配多相機
// 在渲染循環中使用當前相機
function animate() {requestAnimationFrame(animate);// 獲取當前激活的相機const activeCamera = cameras[currentCamera.value];// 旋轉場景物體scene.traverse(obj => {if (obj.isMesh) obj.rotation.y += 0.01;});renderer.render(scene, activeCamera);
}
4.4 相機切換效果對比
5. 高級技巧:相機控制器
5.1 引入OrbitControls
npm install three-orbitcontrols
<script setup>
import { OrbitControls } from 'three-orbitcontrols';onMounted(() => {const controls = new OrbitControls(camera, renderer.domElement);// 配置控制器參數controls.enableDamping = true; // 啟用阻尼效果controls.dampingFactor = 0.05; // 阻尼系數controls.autoRotate = true; // 自動旋轉controls.autoRotateSpeed = 1.0;// 在渲染循環中更新控制器function animate() {requestAnimationFrame(animate);controls.update(); // 必須每幀更新renderer.render(scene, camera);}
});
</script>
5.2 控制器限制設置
// 限制垂直旋轉角度
controls.minPolarAngle = Math.PI / 6; // 30度
controls.maxPolarAngle = Math.PI / 2; // 90度// 禁用平移
controls.enablePan = false;// 縮放限制
controls.minDistance = 3;
controls.maxDistance = 15;
6. 常見問題解答
Q1:物體在場景中不可見怎么辦?
- 檢查物體是否添加到場景
scene.add(mesh)
- 確認相機位置是否在物體前方
- 驗證物體是否在相機裁剪范圍內
Q2:如何實現畫布透明背景?
const renderer = new THREE.WebGLRenderer({alpha: true, // 開啟透明度premultipliedAlpha: false // 避免顏色預乘
});
scene.background = null; // 清除場景背景
Q3:為什么正交相機看到的物體是扁平的?
- 調整正交相機參數范圍:
// 正確設置左右上下參數的比例關系
const aspect = window.innerWidth / window.innerHeight;
const height = 10;
const width = height * aspect;const camera = new THREE.OrthographicCamera(-width/2, width/2, // left, rightheight/2, -height/2, // top, bottom1, 1000
);
7. 總結
通過本篇學習,你已掌握:
- 場景的層級管理技巧(使用Group組織對象)
- 透視相機與正交相機的核心區別及適用場景
- 渲染器的關鍵配置項(抗鋸齒/陰影/響應式)
- Vue3中實現多相機切換系統
- 使用OrbitControls實現交互控制
核心原理:Three.js的渲染流程本質上是將場景中的3D對象,通過相機的視角轉換,最終由渲染器投影到2D畫布上的過程。
下一篇預告
第三篇:幾何體入門:內置幾何體全解析
你將學習:
- 12種基礎幾何體的創建與參數調整
- 幾何體頂點(Vertex)與面(Face)的底層原理
- 動態生成參數化幾何體(如可調節分段數的球體)
- 幾何體性能優化技巧(BufferGeometry詳解)
- Vue3實現幾何體參數實時調節面板
準備好探索Three.js的幾何世界了嗎?讓我們從最簡單的立方體開始,逐步揭開3D建模的神秘面紗!