前言
接上一篇文章# html页面3D模型渲染之——three.js,进行了更深的研究,之前只是把模型渲染出来了。
简单的进行预览,后面就想着能不能换肤(因为3D看车,一般都是可以换色的),网上找了好多的例子,都满足不了我的需求,很多都是官网的例子拿来渲染的,我也把那些demo下载下来,换上自己的模型的时候,无论如何都渲染不上颜色,也不知道哪里的问题。
说实话three.JS对初学者确实不友好,一定要大量的时间去研究才可行(后面也没时间去研究,网址上面也就只上了简单的预览)。
直到昨天看到一篇文字,这里引用一下一篇文章# threejs3D汽车换肤实战 当然也是three.js官方的demo,不过这里说的挺详细的。一些具体的解释可以去看这篇文章。
我说一下,需要注意的问题,不然就还是和官网一样,换上自己的模型就渲染不了。 先看效果
重点
里面有这么一段代码,它就是渲染颜色的
loader.load('./models/gltf/ferrari.glb', function (gltf) {
const carModel = gltf.scene.children[0];
console.log(carModel);
carModel.getObjectByName('body').material = bodyMaterial;
carModel.getObjectByName('rim_fl').material = detailsMaterial;
carModel.getObjectByName('rim_fr').material = detailsMaterial;
carModel.getObjectByName('rim_rr').material = detailsMaterial;
carModel.getObjectByName('rim_rl').material = detailsMaterial;
carModel.getObjectByName('trim').material = detailsMaterial;
carModel.getObjectByName('glass').material = glassMaterial;
wheels.push(
carModel.getObjectByName('wheel_fl'),
carModel.getObjectByName('wheel_fr'),
carModel.getObjectByName('wheel_rl'),
carModel.getObjectByName('wheel_rr')
);
//shadow
const mesh = new THREE.Mesh(
new THREE.PlaneGeometry(0.655 * 4, 1.3 * 4),
new THREE.MeshBasicMaterial({
map: shadow, blending: THREE.MultiplyBlending, toneMapped: false, transparent: true
})
);
//设置阴影效果x轴方向的角度
mesh.rotation.x = -Math.PI / 2 ;
mesh.renderOrder = 2;
carModel.add(mesh);
scene.add(carModel);
});
这段代码的解释就是
上面的代码分别是获取模型中车身区域(body),获取轮毂区域(rim_fl、rim_fr、rim_rr、rim_rl)、座椅区域(trim)、玻璃区域(glass)
当然如果是我们自己的模型,复制这段代码,肯定是渲染不出来颜色的。
那么我们需要怎么做呢,肯定是替换我们自己模型的名字,也就是,你模型每块地方的名字(也就是图层)“可以这么去理解,你ps做图的时候,肯定是一块块的图层拼起来的,而这个图层的名称就是你模型的的名称”
上面汽车的名称就是(rim_fl、rim_fr、rim_rr、rim_rl)代表前左、前右、后左、后右的轮毂,车辆的玻璃部分的名字叫做glass,等
那么我们要如何看自己模型的名称呢,很简单
// 打印模型中的所有对象名称
carModel.traverse(function (child) {
if (child.isMesh) {
console.log(child.name);
}
});
这是我打印出来的名称
很多,因为这是图层太多了,他每个图层的名称都打印出来了,这时候你可以去跟公司设计这个模型的人,说一下,看能不能合并一下图层,
不合并也没关系,那你就找到你要渲染区域的名称,然后,比如我的就是这样
loader.load('./3D/BS-36KS.glb', function (gltf) {
const carModel = gltf.scene;
// 打印模型中的所有对象名称
carModel.traverse(function (child) {
if (child.isMesh) {
console.log(child.name);
}
});
carModel.getObjectByName( '机箱主体(645A35A7-9576-4813-A74A-DB3A21C92CF3)' ).material = bodyMaterial;
carModel.getObjectByName( '机箱外壳(5FFEA2F7-BAC5-4065-AA8B-A0A88CF6B687)' ).material = detailsMaterial;
scene.add(carModel);
progressBar.style.display = 'none';
},
就渲染了两个区域,然后你运行一下代码,换肤就成功了。
还有一个需要注意的地方就是,材质,每个区域的材质是不一样的,还是用车demo来举例,
//汽车body的材质。采用了物理网格材质,车漆具有反光效果
const bodyMaterial = new THREE.MeshPhysicalMaterial({
color: 0x333333, metalness: 1.0, roughness: 0.5, clearcoat: 1.0, clearcoatRoughness: 0.03
});
//汽车轮毂的材质,采用了标准网格材质,threejs解析gltf模型,会用两种材质PBR材质去解析
const detailsMaterial = new THREE.MeshStandardMaterial({
color: 0xffffff, metalness: 1.0, roughness: 0.5
});
//汽车玻璃的材质
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff, metalness: 0.25, roughness: 0, transmission: 1.0
});
而官网也提个了,很多材质,可以去研究研究。
附上链接 three.js
总结
至此我想要的功能就完成了,说的可能不够好,也有可能说的的不正确,这些只是我的思路,和见解,也是在别人的demo上面去改的,当然欢迎大家评论,或者有什么不懂的地方,都可以说出来,或许我也不懂呢,哈哈。