Threejs_06 多材质的实现

Threejs 同一个几何体如何实现多材质呢?

多材质的实现

1.使用索引绘制一个几何体

//创建几何体(三角形)
const geometry = new THREE.BufferGeometry();

//使用索引绘制  (两个共用的)
const vertices = new Float32Array([
  -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0,
]);
//创建顶点属性
geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
//创建索引
const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
//创建索引属性
geometry.setIndex(new THREE.BufferAttribute(indices, 1));

2. 设置顶点组(为了方便应用材质)

// 设置2个顶点组 形成两个材质 顶点0开始 添加3个顶点 用的是第一个材质(第三个参数)
geometry.addGroup(0, 3, 0);
geometry.addGroup(3, 3, 1); //顶点3开始 添加三个顶点 第二个材质

3.创建两个材质

//创建材质
const material = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  // wireframe: true,
  // side: THREE.DoubleSide,
});
const material1 = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  // wireframe: true,
});

4. 构建几何体

const plane = new THREE.Mesh(geometry, [material, material1]);
//现在就有两个材质了
scene.add(plane);

 

多材质绘制立方体

1. 做一个立方体的物料

// 创建一个集合体  (立方体)
const cubegeometry = new THREE.BoxGeometry(1, 1, 1);

2. 做立方体六个面的六个材质

// 创建材质 (16进制颜色)
const cubematerial0 = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  //线框
  // wireframe: true,
});
const cubematerial1 = new THREE.MeshBasicMaterial({
  color: 0xff0000,
});
const cubematerial2 = new THREE.MeshBasicMaterial({
  color: 0x0000ff,
});
const cubematerial3 = new THREE.MeshBasicMaterial({
  color: 0xffff00,
});
const cubematerial4 = new THREE.MeshBasicMaterial({
  color: 0x00ffff,
});
const cubematerial5 = new THREE.MeshBasicMaterial({
  color: 0xff00ff,
});

3. 创建立方体

// 创建网格体
const cube = new THREE.Mesh(cubegeometry, [
  cubematerial0,
  cubematerial1,
  cubematerial2,
  cubematerial3,
  cubematerial4,
  cubematerial5,
]);
//移动一下
cube.position.set(2, 0, 0);
// 添加到场景中
scene.add(cube);

  

一个六面六个不同材质的立方体就做好了。

 所有代码

//1.一个物体可以设置多个材质嘛

//1.设置定点组
//2 多个

//导入 threejs
import * as THREE from "three";
//导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//导入lil.gui
// import * as dat from "dat.gui";  // 旧
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";

// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera(
  45, // 视角
  window.innerWidth / window.innerHeight, // 宽高比 窗口的宽高进行设置的
  0.1, // 近平面   相机最近最近能看到的物体
  1000 // 远平面   相机最远能看到的物体
);
// 创建渲染器
const renderer = new THREE.WebGLRenderer();
// 设置渲染器的大小  (窗口大小)
renderer.setSize(window.innerWidth, window.innerHeight);
// 将渲染器的dom元素添加到body中
document.body.appendChild(renderer.domElement);

// 创建一个集合体  (立方体)
const cubegeometry = new THREE.BoxGeometry(1, 1, 1);
console.log(cubegeometry);
// 创建材质 (16进制颜色)
const cubematerial0 = new THREE.MeshBasicMaterial({
  color: 0x00ff00,
  //线框
  // wireframe: true,
});
const cubematerial1 = new THREE.MeshBasicMaterial({
  color: 0xff0000,
});
const cubematerial2 = new THREE.MeshBasicMaterial({
  color: 0x0000ff,
});
const cubematerial3 = new THREE.MeshBasicMaterial({
  color: 0xffff00,
});
const cubematerial4 = new THREE.MeshBasicMaterial({
  color: 0x00ffff,
});
const cubematerial5 = new THREE.MeshBasicMaterial({
  color: 0xff00ff,
});
// 创建网格体
const cube = new THREE.Mesh(cubegeometry, [
  cubematerial0,
  cubematerial1,
  cubematerial2,
  cubematerial3,
  cubematerial4,
  cubematerial5,
]);
//移动一下
cube.position.set(2, 0, 0);
// 添加到场景中
scene.add(cube);

// //创建几何体(三角形)
// const geometry = new THREE.BufferGeometry();

// //使用索引绘制  (两个共用的)
// const vertices = new Float32Array([
//   -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0,
// ]);
// //创建顶点属性
// geometry.setAttribute("position", new THREE.BufferAttribute(vertices, 3));
// //创建索引
// const indices = new Uint16Array([0, 1, 2, 2, 3, 0]);
// //创建索引属性
// geometry.setIndex(new THREE.BufferAttribute(indices, 1));

// // 设置2个顶点组 形成两个材质 顶点0开始 添加3个顶点 用的是第一个材质(第三个参数)
// geometry.addGroup(0, 3, 0);
// geometry.addGroup(3, 3, 1); //顶点3开始 添加三个顶点 第二个材质

// //创建材质
// const material = new THREE.MeshBasicMaterial({
//   color: 0x00ff00,
//   // wireframe: true,
//   // side: THREE.DoubleSide,
// });
// const material1 = new THREE.MeshBasicMaterial({
//   color: 0xff0000,
//   // wireframe: true,
// });

// const plane = new THREE.Mesh(geometry, [material, material1]);
// //现在就有两个材质了
// scene.add(plane);

// 设置相机的位置
camera.position.z = 5;
// 为了看到z轴
camera.position.y = 2;
// 设置x轴
camera.position.x = 2;
//设置相机的焦点 (相机看向哪个点)
camera.lookAt(0, 0, 0);

//添加世界坐标辅助器  (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
const axesHelper = new THREE.AxesHelper(5);
//添加到场景之中
scene.add(axesHelper);

// 添加轨道控制器 (修改侦听位置)  一般监听画布的事件  不监听document.body
const controls = new OrbitControls(camera, renderer.domElement);
// 这里传递阻塞掉了 会导致无法点击
// const controls = new OrbitControls(camera, document.body);

// // 设置带阻尼的旋转
// controls.enableDamping = true;
// // 设置阻尼系数
// controls.dampingFactor = 0.01;
// // 自动旋转
// controls.autoRotate = false;

//渲染函数
function animate() {
  controls.update();
  //请求动画帧
  requestAnimationFrame(animate);
  //旋转网格体
  // cube.rotation.x += 0.01;
  // cube.rotation.y += 0.01;
  //渲染
  renderer.render(scene, camera);
}
animate();
//渲染

// 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
window.addEventListener("resize", () => {
  // 重新设置渲染器的大小
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 重新设置相机的宽高比
  camera.aspect = window.innerWidth / window.innerHeight;
  // 重新计算相机的投影矩阵
  camera.updateProjectionMatrix();
});



//1.gui控制按钮
let eventObj = {
  Fullscreen: function () {
    // 全屏 (画布)
    // renderer.domElement.requestFullscreen();
    // 全屏 (document.body)  可以看到写入的按钮
    document.body.requestFullscreen();
  },
  exitFullscreen: function () {
    // 退出全屏
    document.exitFullscreen();
  },
};

//创建gui实例
const gui = new GUI();
//添加按钮  第一个参数为对象实例  第二个参数为对象中属性名称
gui.add(eventObj, "Fullscreen").name("全屏");
//退出按钮
gui.add(eventObj, "exitFullscreen").name("退出全屏");

//2.gui控制立方体的位置
// gui.add(cube.position, "x", -5, 5).name("立方体x轴位置");