自造冰墩墩!用Threejs自己实现一个冰墩墩!

Posted 小北哥哥和北妈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自造冰墩墩!用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~

以上是关于自造冰墩墩!用Threejs自己实现一个冰墩墩!的主要内容,如果未能解决你的问题,请参考以下文章

怎么用易语言写一个冰墩墩

用C语言代码实现一只可爱的冰墩墩!

HarmonyOS 纯css3版冰墩墩

冬奥快结束了还没有抢到冰墩墩?程序员一招让你不用排队不用愁!

#私藏项目实操分享#利用鸿蒙JavaUI 框架的 WebView 加载本地冰墩墩网页

冰墩墩是怎么选出来的呢?