系列文章目录
- React 使用 three.js 加载 gltf 3D模型 | three.js 入门
- React + three.js 3D模型骨骼绑定
- React + three.js 3D模型面部表情控制
示例项目(github):https://github.com/couchette/simple-react-three-facial-expression-demo
示例项目(gitcode):https://gitcode.com/qq_41456316/simple-react-three-facial-expression-demo
文章目录
- 系列文章目录
- 前言
- 一、实现步骤
- 1、创建项目配置环境
- 2. 创建组件
- 3. 使用组件
- 4. 运行项目
- 总结
前言
在本系列的上一篇文章中,我们已经探讨了如何在 React 中利用 three.js 来渲染 3D 模型,现在,我们将深入研究如何运用 three.js 控制这些模型的表情。让我们一同探索如何赋予你的 3D 模型更加生动和丰富的表情吧!
一、实现步骤
1、创建项目配置环境
使用 create-reacte-app 创建项目
npx create-react-app simple-react-three-facial-expression-demo
cd simple-react-three-facial-expression-demo
安装three.js
npm i three
2. 创建组件
在src
目录创建components
文件夹,在components
文件夹下面创建ThreeContainer.js
文件。
首先创建组件,并获取return 元素的ref
import * as THREE from "three";
import { useRef, useEffect } from "react";function ThreeContainer() {const containerRef = useRef(null);const isContainerRunning = useRef(false);return <div ref={containerRef} />;
}export default ThreeContainer;
接着将three.js自动创建渲染元素添加到return组件中为子元素(可见container.appendChild(renderer.domElement);
),相关逻辑代码在useEffect中执行,完整代码内容如下
import * as THREE from "three";import WebGPU from "three/addons/capabilities/WebGPU.js";
import WebGL from "three/addons/capabilities/WebGL.js";import WebGPURenderer from "three/addons/renderers/webgpu/WebGPURenderer.js";import Stats from "three/addons/libs/stats.module.js";import { OrbitControls } from "three/addons/controls/OrbitControls.js";import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { KTX2Loader } from "three/addons/loaders/KTX2Loader.js";
import { MeshoptDecoder } from "three/addons/libs/meshopt_decoder.module.js";import { GUI } from "three/addons/libs/lil-gui.module.min.js";
import { useRef, useEffect } from "react";function ThreeContainer() {const containerRef = useRef(null);const isContainerRunning = useRef(false);useEffect(() => {if (!isContainerRunning.current && containerRef.current) {isContainerRunning.current = true;init();}async function init() {if (WebGPU.isAvailable() === false &&WebGL.isWebGL2Available() === false) {containerRef.current.appendChild(WebGPU.getErrorMessage());throw new Error("No WebGPU or WebGL2 support");}let mixer;const clock = new THREE.Clock();const container = containerRef.current;const camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,20);camera.position.set(-1.8, 0.8, 3);const scene = new THREE.Scene();scene.add(new THREE.HemisphereLight(0xffffff, 0x443333, 2));const renderer = new WebGPURenderer({ antialias: true });renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);renderer.toneMapping = THREE.ACESFilmicToneMapping;renderer.setAnimationLoop(animate);container.appendChild(renderer.domElement);const ktx2Loader = await new KTX2Loader().setTranscoderPath("/basis/").detectSupportAsync(renderer);new GLTFLoader().setKTX2Loader(ktx2Loader).setMeshoptDecoder(MeshoptDecoder).load("models/facecap.glb", (gltf) => {const mesh = gltf.scene.children[0];scene.add(mesh);mixer = new THREE.AnimationMixer(mesh);mixer.clipAction(gltf.animations[0]).play();// GUIconst head = mesh.getObjectByName("mesh_2");const influences = head.morphTargetInfluences;//head.morphTargetInfluences = null;// WebGPURenderer: Unsupported texture format. 33776head.material.map = null;const gui = new GUI();gui.close();for (const [key, value] of Object.entries(head.morphTargetDictionary)) {gui.add(influences, value, 0, 1, 0.01).name(key.replace("blendShape1.", "")).listen();}});scene.background = new THREE.Color(0x666666);const controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;controls.minDistance = 2.5;controls.maxDistance = 5;controls.minAzimuthAngle = -Math.PI / 2;controls.maxAzimuthAngle = Math.PI / 2;controls.maxPolarAngle = Math.PI / 1.8;controls.target.set(0, 0.15, -0.2);const stats = new Stats();container.appendChild(stats.dom);function animate() {const delta = clock.getDelta();if (mixer) {mixer.update(delta);}renderer.render(scene, camera);controls.update();stats.update();}window.addEventListener("resize", () => {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);});}}, []);return <div ref={containerRef} />;
}export default ThreeContainer;
3. 使用组件
修改App.js的内容如下
import "./App.css";
import ThreeContainer from "./components/ThreeContainer";function App() {return (<div><ThreeContainer /></div>);
}export default App;
4. 运行项目
运行项目npm start
最终效果如下
总结
通过本文的介绍,相信读者对于在 React 中实现 3D 模型表情控制有了初步的了解。如果你对此感兴趣,不妨动手尝试一下,可能会有意想不到的收获。同时,也欢迎大家多多探索,将 React 和 Three.js 的强大功能发挥到极致,为网页应用增添更多的乐趣和惊喜。