大白话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 项目会变得更加高级和炫酷,给用户带来更好的体验。