实现冰墩墩自由了!用Threejs在你的网页里放一个冰墩墩!
前言
最近冬奥会吉祥物冰墩墩真是火出天际,各地冬奥纪念品商店里的冰墩墩都被抢购一空,更有很多没有抢到冰墩墩的朋友们开始呼吁摇号购买或者按一户一墩来计划购买。
实际上冰墩墩的发布时间是2019年11月2号,说实在的,大帅家门口就是北京冬奥公园,附近的冬奥纪念品商店更是早就开门了,遛娃时也去过好多次,就是没有想法要买,谁知道现在还一墩难求 -_- !
如何让大家都可以人手一个冰墩墩呢?作为一个Web前端工程师,这篇文章我就分享一个在网页里展示冰墩墩的源码,迅速让大家实现冰墩墩自由!
Threejs基础场景
首先当然也是最重要的,你必须得有冰墩墩的3D模型。而这最重要的一环,大帅花了3美刀已经为大家买来了。
接下来我们用Threejs把冰墩墩在网页里显示出来。大帅之前写过几篇Threejs的文章,想要学习网页3D渲染的小伙伴们记得点点赞,后续我还会多更新一些Threejs的教程。
建立基本场景的代码就不细说了,和官方文档中也没有区别。
<!DOCTYPE html>
<html lang="en">
<head>
<title>冰墩墩</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
html,body{
padding:0;
margin:0;
}
</style>
</head>
<body>
<script type="module">
import * as THREE from './js/three.module.js';
import { OrbitControls } from './js/OrbitControls.js';
import { GLTFLoader } from './js/GLTFLoader.js';
let camera, scene, renderer;
init();
render();
function init() {
const container = document.createElement( 'div' );
document.body.appendChild( container );
camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 20 );
camera.position.set( 0, 0, 3 );
scene = new THREE.Scene();
//待插入模型
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
const controls = new OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render ); // use if there is no animation loop
controls.minDistance = 2;
controls.maxDistance = 10;
controls.target.set( 0, 0, - 0.2 );
controls.update();
window.addEventListener( 'resize', onWindowResize );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
render();
}
function render() {
renderer.render( scene, camera );
}
</script>
</body>
</html>
配套视频教程
GLTF模型优点
这里我再给没看过之前文章的小伙伴们分享下GLTF
的格式的特点以及如何在Threejs里加载GLTF模型。
GLTF
格式(图形语言传输格式)是由OpenGL官方维护团队推出的现代3d模型通用格式,可以包含几何体、材质、动画及场景、摄影机等信息,并且文件量还小。有3D模型界的JPEG之称。
过去的工作流里,建模师会建好模型,设置好材质,添加好灯光等等,然后交给程序员照着建模师提供的参数用代码去实现一模一样的效果。而GLTF
模型的好处就是几乎可以省去这个步骤,因为模型文件中已经全部包含了建模师的各种设定。
源码下载
加载GLTF模型
const loader = new GLTFLoader().setPath( 'model/' );
loader.load( 'dwendwen.gltf', function ( gltf ) {
scene.add( gltf.scene );
render();
});
非常简单对不对,但是出来的效果怎么这么阴间呢?我在导出GLTF格式之前设置的可不是这样呀。
可能由于兼容性的问题,脸部的卡通材质丢失了,还有冰晶外壳需要的环境反射贴图也没有了。我也不清楚具体是哪里兼容性的问题,不过,我们依然可以用代码重新把材质给模型加上呀。
//加载一张环境贴图
const envmap = new THREE.TextureLoader().load( "model/env.jpg",function(texture){
const loader = new GLTFLoader().setPath( 'model/' );
loader.load( 'dwendwen.gltf', function ( gltf ) {
//通过遍历场景,找到指定的模型对象
gltf.scene.traverse( function ( child ) {
if(child.name=="outer"||child.name=="mask"){
//找到外壳模型对象添加环境贴图
child.material.envMap = texture;
child.material.envMap.mapping = THREE.EquirectangularReflectionMapping;
child.material.envMapIntensity=2;
}else if(child.name=="body"){
//找到身体模型对象,添加卡通渲染材质
var map = child.material.map;
child.material = new THREE.MeshToonMaterial({map:map});
}
});
scene.add( gltf.scene );
render();
} );
});
设置卡通渲染材质那里map的赋值有点迷对不对?那是因为原本的身体模型对象上就有贴图,我直接拿去作为卡通渲染材质的贴图,省的再加载一遍了。
现在我们的冰墩墩就很BlingBling了对吧~
Enjoy~
本文的最后推荐我好兄弟崔效瑞的Vue3源码课程,。但凡你们在B站看过他的视频教程,都会被他一手行云流水的键盘操作秀到。他就是我眼中硬核程序员。通过这门课的学习,你一定会对Vue3响应式的原理,底层实现,运行时了熟于心,Vue3现在已经正式成为Vue的默认安装版本,2022的大厂面试绝对是必问的问题之一,想在今年跳槽涨薪或者进大厂的伙伴们,现在正是学习的好时机。
长按识别下方二维码即可享受限时优惠价格599元,好像还有10几个小时就会涨价了。