👨⚕️ 主页: gis分享者
👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅!
👨⚕️ 收录于专栏:threejs gis工程师
文章目录
- 一、🍀前言
- 1.1 ☘️THREE.SceneUtils 场景操控类
- 1.2 ☘️.createMultiMaterialObject
- 二、🍀使用createMultiMaterialObject创建多材质对象
- 1. ☘️实现思路
- 2. ☘️代码样例
一、🍀前言
本文详细介绍如何基于threejs在三维场景中使用createMultiMaterialObject创建多材质对象,亲测可用。希望能帮助到您。一起学习,加油!加油!
1.1 ☘️THREE.SceneUtils 场景操控类
THREE.SceneUtils一个用于操控场景的实用类。
方法:
.createMeshesFromInstancedMesh ( instancedMesh : InstancedMesh ) : Group
instancedMesh – 实例化网格。
为给定的实例化网格的每个实例,创建一个包含新网格的新物体组(Object Group)。
.createMeshesFromMultiMaterialMesh ( mesh : Mesh ) : Group
mesh – 具有多种材质的网格。
将给定的多材质网格转换为 Group 的实例,为每种材质保留一个单独的网格。
.createMultiMaterialObject ( geometry : BufferGeometry, materials : Array ) : Group
geometry – 材料集的几何形状。materials – 为物体准备的材料。
创建一个新组,囊括了在材质中定义的每种材质的新网格。请注意,这和为一个网格定义多种材质的材质数组不同。
该方法对于同时需要材质和线框绘制的物体非常有用。
.sortInstancedMesh ( mesh : InstancedMesh, compareFn : Function ) : undefined
mesh – InstancedMesh 将在其中对实例进行排序。
compareFn – 定义排序顺序的比较器函数。
根据用户定义的回调,对 InstancedMesh 中的实例进行排序。回调将提供两个参数,indexA 和 indexB,并且必须返回一个数值。有关排序回调及其返回值的更多信息,请参见 Array.prototype.sort。
由于性能成本高,three.js 不会自动对 InstancedMesh 实例进行排序。手动排序可能有助于改善 alpha 混合材质的显示(从后到前),并减少不透明材质的透支(从前到后)。
MaterialObjectfont_39">1.2 ☘️.createMultiMaterialObject
本例使用createMultiMaterialObject创建多材质对象。实现立方体网格对象既有颜色基础材质,又有MeshDepthMaterial深度材质效果。
MaterialObjectfont_41">二、🍀使用createMultiMaterialObject创建多材质对象
1. ☘️实现思路
- 1、初始化renderer渲染器,设置renderer的颜色。
- 2、初始化Scene三维场景scene。
- 3、初始化camera相机,定义相机位置 camera.position.set,设置相机方向camera.lookAt,设置相机的near、far近远端面。
- 4、加载几何模型:定义addCube方法,方法内创建随机大小的立方体几何对象cubeGeometry。创建MeshDepthMateria网格深度材质cubeMaterial和MeshBasicMaterial基础材质colorMaterial。传入参数cubeGeometry、cubeMaterial和colorMaterial调用createMultiMaterialObject方法创建多材质对象cube,设置cube第一个网格对象的大小、cube的投影和随机位置,场景scene中添加cube。循环10次调用addCube方法生成多材质对象。定义render方法,实现所有立方体对象的旋转动画。具体代码参考下面代码样例。
- 5、加入gui控件,控制添加、移除立方体以及立方体颜色、旋转速度等信息。加入stats监控器,监控帧数信息。
2. ☘️代码样例
<!DOCTYPE html>
<html>
<head>
<title>学习threejs,使用createMultiMaterialObject创建多材质对象</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 {
/* set margin to 0 and overflow to hidden, to go fullscreen */
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, 10, 130);
// 创建渲染器,设置大小
var renderer = new THREE.WebGLRenderer();
renderer.sortObjects = false;
renderer.setClearColor(new THREE.Color(0x00000, 1.0));
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
// 设置相机位置、远近和方向
camera.position.x = -50;
camera.position.y = 40;
camera.position.z = 50;
camera.near = 7;
camera.far = 139;
camera.lookAt(scene.position);
// 渲染器绑定html页面要素
document.getElementById("WebGL-output").appendChild(renderer.domElement);
var step = 0;
var controls = new function () {
this.cameraNear = camera.near;
this.cameraFar = camera.far;
this.rotationSpeed = 0.02;
this.numberOfObjects = scene.children.length;
this.color = 0x00ff00;
this.removeCube = function () {
var allChildren = scene.children;
var lastObject = allChildren[allChildren.length - 1];
if (lastObject instanceof THREE.Mesh) {
scene.remove(lastObject);
this.numberOfObjects = scene.children.length;
}
};
this.addCube = function () {
var cubeSize = Math.ceil(3 + (Math.random() * 3));
var cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
//var cubeMaterial = new THREE.MeshLambertMaterial({color: Math.random() * 0xffffff });
var cubeMaterial = new THREE.MeshDepthMaterial();
var colorMaterial = new THREE.MeshBasicMaterial({
color: controls.color,
transparent: true,
blending: THREE.MultiplyBlending
});
var cube = new THREE.SceneUtils.createMultiMaterialObject(cubeGeometry, [colorMaterial, cubeMaterial]);
cube.children[1].scale.set(0.99, 0.99, 0.99);
cube.castShadow = true;
// 立方体随机位置
cube.position.x = -60 + Math.round((Math.random() * 100));
cube.position.y = Math.round((Math.random() * 10));
cube.position.z = -100 + Math.round((Math.random() * 150));
// 场景中添加立方体
scene.add(cube);
this.numberOfObjects = scene.children.length;
};
this.outputObjects = function () {
console.log(scene.children);
}
};
var gui = new dat.GUI();
gui.addColor(controls, 'color');
gui.add(controls, 'rotationSpeed', 0, 0.5);
gui.add(controls, 'addCube');
gui.add(controls, 'removeCube');
gui.add(controls, 'cameraNear', 0, 50).onChange(function (e) {
camera.near = e;
});
gui.add(controls, 'cameraFar', 50, 200).onChange(function (e) {
camera.far = e;
});
var i = 0;
while (i < 10) {
controls.addCube();
i++;
}
render();
function render() {
stats.update();
// 立方体旋转动画
scene.traverse(function (e) {
if (e instanceof THREE.Mesh) {
e.rotation.x += controls.rotationSpeed;
e.rotation.y += controls.rotationSpeed;
e.rotation.z += 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>
效果如下: