👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:threejs gis工程师
文章目录
- 一、🍀前言
- 1.1 ☘️THREE.MeshFaceMaterial
- 二、🍀使用MeshFaceMaterial面材质容器
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于threejs在三维场景中使用MeshFaceMaterial面材质容器,亲测可用。希望能帮助到您。一起学习,加油!加油!
1.1 ☘️THREE.MeshFaceMaterial
THREE.MeshFaceMaterial是一个材质容器,用于为几何体的每个面分配不同的材质。
代码示例:
// 创建材质数组,并为每个面指定不同的材质
const faceMaterialArray = [];
faceMaterialArray.push(new THREE.MeshBasicMaterial({ color: 0x009e60 }));
faceMaterialArray.push(new THREE.MeshBasicMaterial({ color: 0x0051ba }));
faceMaterialArray.push(new THREE.MeshBasicMaterial({ color: 0xffd500 }));
faceMaterialArray.push(new THREE.MeshBasicMaterial({ color: 0xff5800 }));
faceMaterialArray.push(new THREE.MeshBasicMaterial({ color: 0xc41e3a }));
faceMaterialArray.push(new THREE.MeshBasicMaterial({ color: 0xffffff }));// 注意:对于立方体,由于每个面由两个三角形组成,因此我们需要为每个面指定两个相同的材质。
// 但为了简化示例,这里只为每个“可见”面指定了一个材质,另一个三角形面将使用相同的材质。// 实例化MeshFaceMaterial
const faceMaterial = new THREE.MeshFaceMaterial(faceMaterialArray);// 创建几何体并应用材质
const cubeGeom = new THREE.BoxGeometry(3, 3, 3);
const cube = new THREE.Mesh(cubeGeom, faceMaterial);// 将几何体添加到场景中(这里假设已经有一个场景对象scene)
scene.add(cube);
替代方案:
在 Three.js 中,MeshFaceMaterial 是一个历史遗留的材质类,用于为几何体(Geometry)的每个面(Face)分配不同的材质。不过,自 Three.js r125+ 版本后,随着 Geometry 类被废弃并逐步替换为 BufferGeometry,MeshFaceMaterial 也已被弃用。
BufferGeometry + 多材质
- (1) 使用多材质组(groups)
将几何体划分为多个材质组,每组对应一个材质。
const geometry = new THREE.BufferGeometry();
const material1 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });// 假设几何体有 6 个面(立方体)
geometry.groups.push({ start: 0, count: 3, materialIndex: 0 }, // 前3个顶点用材质0{ start: 3, count: 3, materialIndex: 1 } // 后3个顶点用材质1
);// 创建网格时传入材质数组
const mesh = new THREE.Mesh(geometry, [material1, material2]);
- (2) 使用多材质组(groups)
通过顶点颜色或纹理坐标实现面级差异化效果。
// 顶点颜色示例
const colors = new Float32Array([1, 0, 0, // 顶点1颜色(红)1, 0, 0, 1, 0, 0, 0, 1, 0, // 顶点4颜色(绿)0, 1, 0, 0, 1, 0
]);
geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));const material = new THREE.MeshBasicMaterial({ vertexColors: true });
const mesh = new THREE.Mesh(geometry, material);
二、🍀使用MeshFaceMaterial面材质容器
1. ☘️实现思路
- 1、初始化renderer渲染器。
- 2、初始化Scene三维场景scene。
- 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt。
- 4、创建THREE.SpotLight聚光灯光源spotLight,设置聚光灯光源位置和投影,scene场景加入spotLight。
- 5、加载几何模型:创建二维平面网格对象plane,设置plane的旋转角度和位置,scene场景加入plane。定义数组变量mats,mats添加六个THREE.MeshBasicMaterial基础材质作为立方体的六个面材质,六个基础材质设置为不同颜色。传入mats参数创建MeshFaceMaterial面材质容器faceMaterial。创建THREE.Mesh网格group,x、y、z方向循环使用faceMaterial材质创建27个小立方体cube,设置cube位置,group添加cube。scene场景添加group。定义render方法,实现立方体魔方group的旋转动画。具体代码参考下面代码样例。
- 6、加入gui控件,控制group的旋转速度。加入stats监控器,监控帧数信息。
2. ☘️代码样例
<!DOCTYPE html>
<html>
<head><title>学习threejs,使用MeshFaceMaterial面材质容器</title><script type="text/javascript" src="../libs/three.js"></script><script type="text/javascript" src="../libs/stats.js"></script><script type="text/javascript" src="../libs/dat.gui.js"></script><style>body {margin: 0;overflow: hidden;}</style>
</head>
<body><div id="Stats-output">
</div>
<!-- Div which will hold the Output -->
<div id="WebGL-output">
</div><!-- Js 代码块 -->
<script type="text/javascript">// 初始化function init() {var stats = initStats();// 创建三维场景var scene = new THREE.Scene();// 创建相机var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);// 创建渲染器,设置颜色和大小var renderer = new THREE.WebGLRenderer();renderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));renderer.setSize(window.innerWidth, window.innerHeight);renderer.shadowMapEnabled = false;// 创建二维平面,并设置投影var planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1);var planeMaterial = new THREE.MeshLambertMaterial({color: 0xffffff});var plane = new THREE.Mesh(planeGeometry, planeMaterial);plane.receiveShadow = true;// 设置二维平面的位置和旋转角度plane.rotation.x = -0.5 * Math.PI;plane.position.x = 0;plane.position.y = -2;plane.position.z = 0;// 场景scene添加二维平面scene.add(plane);// 设置相机位置和方向camera.position.x = -40;camera.position.y = 40;camera.position.z = 40;camera.lookAt(scene.position);// 添加聚光灯光源,设置光源位置和投影var spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-40, 60, -10);spotLight.castShadow = true;scene.add(spotLight);// renderer渲染器绑定html要素document.getElementById("WebGL-output").appendChild(renderer.domElement);var group = new THREE.Mesh();// 添加立方体六个面材质var mats = [];mats.push(new THREE.MeshBasicMaterial({color: 0x009e60}));mats.push(new THREE.MeshBasicMaterial({color: 0x0051ba}));mats.push(new THREE.MeshBasicMaterial({color: 0xffd500}));mats.push(new THREE.MeshBasicMaterial({color: 0xff5800}));mats.push(new THREE.MeshBasicMaterial({color: 0xC41E3A}));mats.push(new THREE.MeshBasicMaterial({color: 0xffffff}));var faceMaterial = new THREE.MeshFaceMaterial(mats);// 创建27个小立方体组成大立方体for (var x = 0; x < 3; x++) {for (var y = 0; y < 3; y++) {for (var z = 0; z < 3; z++) {var cubeGeom = new THREE.BoxGeometry(2.9, 2.9, 2.9);var cube = new THREE.Mesh(cubeGeom, faceMaterial);cube.position.set(x * 3 - 3, y * 3, z * 3 - 3);group.add(cube);}}}scene.add(group);var step = 0;var controls = new function () {this.rotationSpeed = 0.02;this.numberOfObjects = scene.children.length;};var gui = new dat.GUI();gui.add(controls, 'rotationSpeed', 0, 0.5);render();function render() {stats.update();group.rotation.y = step += controls.rotationSpeed;requestAnimationFrame(render);renderer.render(scene, camera);}function initStats() {var stats = new Stats();stats.setMode(0);stats.domElement.style.position = 'absolute';stats.domElement.style.left = '0px';stats.domElement.style.top = '0px';document.getElementById("Stats-output").appendChild(stats.domElement);return stats;}}window.onload = init;
</script>
</body>
</html>
效果如下: