学习threejs,使用MeshFaceMaterial面材质容器
👨⚕️ 主页: 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>
效果如下: