大白话react第十九章React 与 WebGL 项目的深度拓展和优化
1. 实现 VR/AR 交互体验
在 3D 网页应用里加入虚拟现实(VR)或者增强现实(AR)功能,能让用户有更沉浸的体验。就好比用户戴上 VR 眼镜,就能感觉自己身处 3D 场景之中;使用 AR 时,能把虚拟物体叠加到现实世界里。我们使用 three.js
和 webxr
来实现这些功能。
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';
// 引入 OrbitControls 用于控制相机视角
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';const VRARComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建 three.js 的场景const scene = new THREE.Scene();// 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建 WebGL 渲染器,并开启 XR 支持const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);renderer.xr.enabled = true; // 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 创建一个立方体几何体const geometry = new THREE.BoxGeometry();// 创建一个基本材质,颜色为蓝色const material = new THREE.MeshBasicMaterial({ color: 0x0000ff });// 创建一个网格对象,将几何体和材质组合在一起const cube = new THREE.Mesh(geometry, material);// 将立方体添加到场景中scene.add(cube);// 设置相机位置camera.position.z = 5;// 创建轨道控制器,方便用户在普通模式下控制相机视角const controls = new OrbitControls(camera, renderer.domElement);// 定义渲染函数const animate = () => {// 请求下一帧动画renderer.setAnimationLoop(() => {// 让立方体绕 x 轴和 y 轴旋转cube.rotation.x += 0.01;cube.rotation.y += 0.01;// 渲染场景renderer.render(scene, camera);});};// 开始动画循环animate();// 创建一个按钮用于进入 VR 模式const vrButton = document.createElement('button');vrButton.textContent = '进入 VR 模式';vrButton.addEventListener('click', async () => {try {await renderer.xr.setSession(await navigator.xr.requestSession('immersive-vr'));} catch (error) {console.error('无法启动 VR 会话:', error);}});containerRef.current.appendChild(vrButton);// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);containerRef.current.removeChild(vrButton);};}, []);return (// 创建一个 div 用于存放 3D 场景<div ref={containerRef} />);
};export default VRARComponent;
2. 进行大规模场景优化
当场景里的物体数量特别多的时候,渲染会变得很慢。我们可以通过分层渲染、遮挡剔除等方法来优化性能,让大规模场景也能流畅显示。这里我们简单模拟一下分层渲染的思路。
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';const LargeScaleSceneComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建 three.js 的场景const scene = new THREE.Scene();// 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建 WebGL 渲染器const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);// 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 创建多个层,用于分层渲染const layer1 = new THREE.Group();const layer2 = new THREE.Group();scene.add(layer1);scene.add(layer2);// 在第一层添加一些立方体for (let i = 0; i < 10; i++) {const geometry = new THREE.BoxGeometry();const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });const cube = new THREE.Mesh(geometry, material);cube.position.x = i * 2;layer1.add(cube);}// 在第二层添加一些球体for (let i = 0; i < 10; i++) {const geometry = new THREE.SphereGeometry(0.5, 32, 32);const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });const sphere = new THREE.Mesh(geometry, material);sphere.position.x = i * 2;layer2.add(sphere);}// 设置相机位置camera.position.z = 15;// 定义渲染函数const animate = () => {// 请求下一帧动画requestAnimationFrame(animate);// 渲染场景renderer.render(scene, camera);};// 开始动画循环animate();// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (// 创建一个 div 用于存放 3D 场景<div ref={containerRef} />);
};export default LargeScaleSceneComponent;
3. 实现实时阴影与动态光照
让场景里的阴影和光照能随着物体的移动实时变化,这样场景会更真实。我们可以利用 three.js
的光照和阴影功能来实现。
// 引入 React 的 useEffect 和 useRef 钩子
import React, { useEffect, useRef } from'react';
// 引入 three.js 用于创建 3D 场景
import * as THREE from 'three';const RealTimeShadowsComponent = () => {// 创建一个 ref 用于引用存放 3D 场景的 DOM 元素const containerRef = useRef(null);useEffect(() => {// 创建 three.js 的场景const scene = new THREE.Scene();// 创建透视相机,设置视角、宽高比、近裁剪面和远裁剪面const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建 WebGL 渲染器,并开启阴影支持const renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);renderer.shadowMap.enabled = true;// 将渲染器的 DOM 元素添加到 ref 对应的 DOM 元素中containerRef.current.appendChild(renderer.domElement);// 创建一个平面几何体,作为地面const planeGeometry = new THREE.PlaneGeometry(10, 10);// 创建平面的材质const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x808080 });// 创建平面的 3D 模型const plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.rotation.x = -Math.PI / 2;// 设置平面接收阴影plane.receiveShadow = true;scene.add(plane);// 创建一个立方体几何体const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);// 创建立方体的材质const cubeMaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff });// 创建立方体的 3D 模型const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);cube.position.y = 0.5;// 设置立方体投射阴影cube.castShadow = true;scene.add(cube);// 创建一个聚光灯,用于产生阴影和光照const spotLight = new THREE.SpotLight(0xffffff, 1);spotLight.position.set(2, 5, 2);spotLight.castShadow = true;scene.add(spotLight);// 设置相机位置camera.position.z = 5;// 定义渲染函数const animate = () => {// 请求下一帧动画requestAnimationFrame(animate);// 让立方体在 x 轴上移动,模拟动态效果cube.position.x = Math.sin(Date.now() * 0.001) * 2;// 渲染场景renderer.render(scene, camera);};// 开始动画循环animate();// 组件卸载时清理资源return () => {containerRef.current.removeChild(renderer.domElement);};}, []);return (// 创建一个 div 用于存放 3D 场景<div ref={containerRef} />);
};export default RealTimeShadowsComponent;
通过这些功能的实现,你的 React 和 WebGL 项目会变得更加高级和炫酷,给用户带来更好的体验。