教你如何利用threejs对3D模型皮肤进行DIY
一步一步教你如何利用threejs加载gltf模型来实现DIY换肤功能。
模型准备
模型制作
模型可以通过网上下载,也可以自己通过c4d、maya、blender等模型制作软件得到。这里就不叙述有关模型制作的问题,本文中会在blender进行模型的有关设置。
模型导出
1、导出前设定
为了在页面中方便后续的操作,在导出模型前,将模型的各个部件拆分好进行命名约定(本文以小车模型为例)具体如下图所示:
图1
2、导出模型格式选取threejs可以加载的模型有很多中,之前.ojb、.json、.FBX等格式都有讲过参我之前的文章从Maya中把模型搬运至网页的过程、首个threejs-3D项目,所以我这里选取官方推荐现在使用的格式.gltf、.glb。
gltf与glb的区别: gltf文件类似与json格式而glb是以二进制流进行存储。
3、模型导出
在blender中直接有gltf格式导出的选项,如果没有特别的要求,按照默认配置导出就可以了。导出界面如下图所示:
图2
场景建立
- 使用threejs建立一个场景
首先将需要的东西从threejs (r110) 中引入,然后进行建立场景四部曲:
import {Scene, WebGLRenderer, PerspectiveCamera, Color} from 'three';
1、Scene
let scene = new Scene();
scene.background = new Color(0xB3CEFB);
scene.fog = new Fog(scene.background, 1, 100);
2、Camera
let camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.z = 15;
3、Render
let renderer = new WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
4、Animate
const render = function () {
requestAnimationFrame(render);
renderer.render(scene, camera);
}
然后就会看到一个蓝蓝的场景(因为设置了背景颜色)
加载模型
- GLTFLoader加载模型至场景
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
const loader = function () {
let gltfLoader = new GLTFLoader();
gltfLoader.load(
'toycar.glb', // your .glb & .gltf
gltf => {
scene.add(gltf.scene); // 添加至建立好的场景中
// gltf.animations; // Array<THREE.AnimationClip>
// gltf.scene; // THREE.Group
// gltf.scenes; // Array<THREE.Group>
// gltf.cameras; // Array<THREE.Camera>
// gltf.asset; // Object
},
() => {
// ..
},
(error) => {
console.log(error);
}
)
}
GLTFLoader加载成功后会返回一个对象,其中scene.children中会包含所导出的所有部件。具体返回以及参数介绍可以查看参考文档。
添加至场景后可以看到一个漆黑的汽车,如下图所示:
图3
这是因为场景中没有光源的照射所以导致漆黑一片,只能看一个轮廓,所以我么需要在建立的场景中增加灯关。
- 添加灯光
threejs中灯光有很多中,这里我们添加DirectionalLight(平行光)HemisphereLight(半球光)
import {
DirectionalLight,
DirectionalLightHelper,
HemisphereLight,
HemisphereLightHelper
} from 'three';
// Helper为灯关的辅助线方便调试
let directionalLight = new DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(-4, 8, 4);
let dhelper = new DirectionalLightHelper(directionalLight, 5, 0xff0000);
let hemisphereLight = new HemisphereLight(0xffffff, 0xffffff, 0.4);
hemisphereLight.position.set(0, 8, 0);
let hHelper = new HemisphereLightHelper(hemisphereLight, 5);
scene.add(directionalLight);
scene.add(hemisphereLight);
添加灯光后效果如图:
图4
- 阴影渲染
接着我们将设置模型的阴影显示,阴影显示需要光源和投射地(阴影显示的地方),现在我们已经有了光源差投射地,所以我们创建一个地板,让阴影投射至地板上,来达到想要的效果:
// 制作一个地板
import {PlaneGeometry, MeshPhongMaterial, Mesh} from 'three';
let floorGeometry = new PlaneGeometry(5000, 5000, 1);
let floorMaterial = new MeshPhongMaterial({
color: 0x77F28F,
shininess: 0,
// wireframe: true
});
let floor = new Mesh(floorGeometry, floorMaterial);
floor.rotation.x = -0.5 * Math.PI;
floor.position.y = -2.1;
scene.add(floor);
现在我们可以看到一个绿色的地板出现在场景中,但是还是不见车子的阴影,这是因为我们还要对光源、渲染器、模型、地板进行设置才能显示阴影:
// 首先渲染器开启阴影
renderer.shadowMap.enabled = true;
// 光源开启阴影
directionalLight.castShadow = true;
directionalLight.shadow.mapSize = new Vector2(1024, 1024);
// 地板接受阴影开启
floor.receiveShadow = true;
// 模型Mesh开启阴影
gltf.scene.traverse(obj => {
if(obj.isMesh) {
obj.castShadow = true;
obj.receiveShadow = true;
}
})
这时候就可以看到小车的阴影渲染到绘制的地板上了,然后你可能会看到车身上有很多条纹状的黑线,这是因为在渲染阴影中产生了伪影,然后我们可以调节light.shadow.bias来解决
directionalLight.shadow.bias = -0.001; // value 自行调节
阴影渲染对比如下图所示:
图5
换肤功能
想要实现各个部件换肤功能,我们需要选中部件,修改选中部件材质来达到我们换肤的功能。
- 部件选中
选取部件其实比较简单,在场景中加入射线检测就可以了,实现如下:
import {Vector2, Vector3, Raycaster} from 'three';
let raycaster = new Raycaster();
let mouse = new Vector2();
document.body.addEventListener('click', selectHandler, false);
const selectHandler = function (ev) {
mouse.x = (ev.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(ev.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
// 这里我们只检测模型的选中情况
let intersects = raycaster.intersectObjects(gltf.scene.children, true);
if (intersects.length > 0) {
let selectedObjects = intersects[0].object;
}
}
- 设置颜色或者纹理
现在我们得到部件,现在只需要修改材质颜色即可。
核心code如下:
let newMaterial = selectedObjects.material.clone();
newMaterial.color = new Color('#D3C542'); //重新修改颜色
selectedObjects.material = newMaterial;
如果需要用图片,那么更改方式更修改图片类似,先用TextureLoader()
加载纹理图,然后设置material.map,最后更新material就可以了。
- 添加选中效果
这里想增加一个选中部件后,那个部件进行外发光的效果,让用户觉得自己是选中了这个部件。这个外发光的效果可以自己用ShaderMaterial()
去实现,我这边用的threejs在postprocessing提供的效果,具体实现如下所示:
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer';
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass';
let composer = new EffectComposer(renderer);
let renderPass = new RenderPass(scene, camera);
composer.addPass(renderPass);
let outlinePass = new OutlinePass(new Vector2(window.innerWidth, window.innerHeight), scene, camera);
composer.addPass(outlinePass);
outlinePass.visibleEdgeColor.set('#130AF2'); // 选中颜色
outlinePass.edgeStrength = 5;
outlinePass.edgeGlow = 1.5;
const render = function () {
requestAnimationFrame(render);
composer.render();
}
功能展示(gif图的效果可能没那么好):
图6
至此使用threejs给3d模型的基本操作就是这样的了,剩下的发挥靠自己想象吧。
其它功能效果
camera-controls
模型的旋转控制,这里直接使用threejs提供的控件
OrbitControls()
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; let controls = new OrbitControls(camera, renderer.domElement);
controls.enablePan = false;
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 3;
controls.enableZoom = false; controls.update();
部件分离动画
分离动画:简单点解释就是给各个部件的位置设置一个开始的点,一个结束点,然后利用TweenLite、TweenMax进行补间动画, 下面以车声为例子:
// 车身上移动画
let component = gltf.scene.getObjectByName('car_body');
TweenLite.to(component.position, 1.5, {
y: 5,
ease: Power4.easeOut
});
重影动画
利用threejs的提供的postprocessing来实现部件移动的时候会产生重影,实现如下:
import { AfterimagePass } from 'three/examples/jsm/postprocessing/AfterimagePass.js'; let afterimagePass = new AfterimagePass(); composer.addPass(afterimagePass);
功能展示(gif图的效果可能没那么好):
图7
最后的最后
如果以上有啥错误或者有啥要交流的欢迎骚扰:(吃口饭不容易!)
wechat: flowers1225
gmail: asdflowers1225@gmail.com
github: https://github.com/flowers1225
教你如何利用threejs对3D模型皮肤进行DIY的更多相关文章
- threejs和3d各种效果的学习
写给即将开始threejs学习的自己,各种尝试,各种记忆.不要怕,灰色的年华终会过去. 一个技术学习的快慢,以及你的深刻程度,还有你的以后遇到这个东西的时候的反应速度,很大程度上,取决于你的博客的深刻 ...
- WPF利用HelixToolKit后台导入3D模型
原文:WPF利用HelixToolKit后台导入3D模型 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/de ...
- ThreeJS 3d模型简介
本文主要是对Threejs中加载模型的支持种类进行简单的知识科普. 3ds (.3ds) 3ds是3ds max通用储存文件格式.使用的范围更宽,可被更多的软件识别使用. amf (.amf) AMF ...
- 3d模型一般怎么导入到到Threejs中使用
这是我之前做的一个demo,导入的3d模型文件是obj格式的,需要使用OBJLoader和MTLLoader, mtl文件用于描述多边形可视面貌的材质如果你可以导出obj.mtl文件的话,那么就可以使 ...
- 在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图
在Jerry写这篇文章时,通过Google才知道,SAP其实是有自己的3D模型视图显示解决方案的. 故事要从Right Hemisphere说起,这是一家专业的企业级2D/3D模型浏览及转换的软件供应 ...
- ifix中嵌入3d模型初探(一)
在ifix项目中插入3d模型,是当前工控上位机的一个发展趋势,故而我也来尝尝鲜.利用现有条件,初步打算完成一个工厂俯视3d全景. 基本思路:利用webbrowser+3dmax+three.js来嵌入 ...
- 转 threejs中3D视野的缩放实现
Threejs基础部分学习知道透视相机new THREE.PerspectiveCamera(fov, aspect , near,far)中. fov视野角(拍摄距离)越大,场景中的物体越小.fov ...
- Flash Stage3D 在2D UI 界面上显示3D模型问题完美解决
一直以来很多Stage3D开发者都在为3D模型在2DUI上显示的问题头疼.Stage3D一直是在 Stage2D下面.为了做到3D模型在2DUI上显示通常大家有几种实现方式,下面来说说这几种实现方式吧 ...
- three.js实现3D模型展示
由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 先看看效果: three.js整体来说 不是很难 只要你静下心来研究研究 很快就会上手的 首先我们在页面上需要创建一个能 ...
随机推荐
- Jupyter自定义设置详解
今天专门花时间总结梳理一下jupyter的一些高级设置,jupyter我已经介绍过一次基本内容了,Setup and Linux | James Chen's Blogs,尤其是如何在服务器运行jup ...
- HF Java Chap 1
介绍了java的工作方式以及几个有趣的小程序 Java的工作模式 大体来说有四个步骤: 源代码 编译器 编译器的输出 Java虚拟机 源代码 这是我们程序员接触到的部分.根据我们面临的问题,编写一个符 ...
- JavaWeb中遇到的字符编码问题
一.常见的编码方式 1.UTF-8 2.ISO-8859-1 二.Tomcat的编码问题 Tomcat8和7的编码方式 Tomcat7对URI默认编码是ISO-8859-1 Tomcat8对URI默认 ...
- 软件工程实验一 Git代码版本管理
实验一 GIT 代码版本管理 一.实验目的: 1)了解分布式分布式版本控制系统的核心机理: 2)熟练掌握git的基本指令和分支管理指令: 二.实验内容: 1)安装git: 2)初始配置git ,gi ...
- Spring Boot 2.x基础教程:使用 ECharts 绘制各种华丽的数据图表
上一节我们介绍了如何在Spring Boot中使用模板引擎Thymeleaf开发Web应用的基础.接下来,我们介绍一下后端开发经常会遇到的一个场景:可视化图表. 通常,这类需求在客户端应用中不太会用到 ...
- direction和writing-mode的介绍
direction介绍 属性值和兼容都很好 CSSdirection属性简单好记,属性值少,兼容性好,关键时候省心省力,是时候给大家宣传宣传,不要埋没了人家的特殊技能. Chrome Safari F ...
- 十分钟复习CSS盒模型与BFC
css盒模型与BFC 本文为收集整理总结网上资源 旨在系统复习css盒模型与bfc 节省复习时间 阅读10分钟 什么是盒模型 每一个文档中,每个元素都被表示为一个矩形的盒子,它都会具有内容区.padd ...
- 前端每日实战:31# 视频演示如何利用 CSS 的动画原理,创作一个乒乓球对打动画
效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/rvgLzK 可交互视频教程 此视频 ...
- 分享一个基于Net Core 3.1开发的模块化的项目
先简单介绍下项目(由于重新基于模块化设计了整个项目,所以目前整个项目功能不多) 1.Asp.Net Core 3.1.2+MSSQL2019(LINUX版) 2.中间件涉及Redis.RabbitMQ ...
- SQLi-Labs之1~6关 - 常规注入与盲注
年初五 财神入 第一关 联合注入 1.准备 2.加'截断 3.order by 判断查询列数 4.同上 5.联合查询判断字段位置 6.查数据库名 7.1 查表名 7.2 查列名 8.查数据 第二关 不 ...