关于webgl:Web3D从0开始学习ThreejsBlender实现甜甜圈掉落效果-大帅老猿threejs特训

52次阅读

共计 4187 个字符,预计需要花费 11 分钟才能阅读完成。

前言

最近大帅邀请胖达老师带来了元宇宙实战特训,具体解说了如何应用 Blender 进行 3D 建模、增加动画以及如何在 Threejs 中展现、管制 3D 模型,让我特地感叹,原来一些看似简单的 3D 我的项目能够如此简略的实现。

Web3D 简介

Web3D 的次要展现形式:
  1. 浏览器间接渲染:电脑浏览器、挪动端浏览器(包含微信浏览器)微信小程序;
  2. 服务端渲染(服务端运行,成果好,经营老本高);将 3D 画面像素推流到前端浏览器 / 小程序展现;
3D 近几年风行的相干概念:
  1. 数字孪生:三维实景模型 + 多系统监控 / 告警数据,实现近程监管(监控、治理);
  2. VR:把人装进虚拟环境
  3. AR:把虚构装进事实
浏览器运行 3D 的计划

ActiveX 插件:IE、Chrome 老版本、Firefox 老版本,已过期;

Flash:时代王者,官网已进行保护;

WebGL:浏览器原生反对(IE11 根本反对,其它浏览器根本都反对)

WebGPU: 性能高,目前还未失去操作系统和浏览器的广泛支持;

可实现公布 WebGL 到浏览器运行的计划(从重到轻):

Unity 引擎:wasm webgl 空包:20m+(不反对 ie11 低版本 chrome 及 Firefox 及国产化)

CocosCreator:webgl 空包:6m+(不反对 ie11 及低版本 chrome 及 firefox)

threejs: webgl 库大小:1m-(开源,IE11 均反对)

babylonjs: webgl 库大小:4m+(微软开源,中文材料绝对较少)

明天咱们就来理解 Three.js

提到 Three.js,不得不先提 OpenGL 和 WebGL,OpenGL 是一个跨平台的 3D/2D 的绘图规范(标准),WebGL(Web Graphics Library)是一种 3D 绘图协定。

WebGL 容许把 JavaScript 和 OpenGL 联合在一起使用,但应用 WebGL 原生的 API 来写 3D 程序十分的简单,同时须要绝对较多的数学知识,对于开发者来说学习老本十分高。

Three.js 是基于 webGL 的封装的一个易于应用且轻量级的 3D 库,Three.js 对 WebGL 提供的接口进行了十分好的封装,简化了很多细节,大大降低了学习老本,极大地提高了性能,性能也十分弱小。

(1)Three.js 官网

(2)Three.js 的 github 地址

起步阶段先从简略开始,间接援用 Three.js,学会最根本的 Three.js 的应用办法
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script src="js/three.min.js"></script>
  <script>
    // 创立场景
    const scene = new THREE.Scene(); 
    // 创立相机,PerspectiveCamera(透视相机),参数(视线角度, 长宽比, 进截面, 远截面)const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); 
    // 渲染器
    const renderer = new THREE.WebGLRenderer();
    // 设置渲染器的宽高
    renderer.setSize(window.innerWidth, window.innerHeight);
    // 将 renderer(渲染器)的 dom 元素(renderer.domElement)增加到咱们的 HTML 文档中
    document.body.appendChild(renderer.domElement);

    // demo-- 立方体
    const geometry = new THREE.BoxGeometry(1, 1, 1); // BoxGeometry 立方体对象
    const material = new THREE.MeshBasicMaterial({ color: 0x00ff00} );  // MeshBasicMaterial 其中的一种材质,设置色彩绿色
    const cube = new THREE.Mesh(geometry, material); // 创建一个网格对象
    scene.add(cube); // 将网格对象增加到场景中
    camera.position.z = 5; 
    
    // 
    function animate() {requestAnimationFrame( animate); // 创立了一个使渲染器可能在每次屏幕刷新时对场景进行绘制的循
      cube.rotation.x += 0.01; // 使正方体能动起来
      cube.rotation.y += 0.01; // 使正方体能动起来
      renderer.render(scene, camera); 
    }
    animate();
  </script>
</body>
</html>
应用 npm 来开发并测试

(1)获取我的项目代码
(2)装置依赖

npm install

(3)开发次要代码 day01_直播代码.js

import * as THREE from 'three';
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {GLTFLoader} from "three/examples/jsm/loaders/GLTFLoader";
import {RGBELoader} from 'three/examples/jsm/loaders/RGBELoader';

let mixer;

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10);
const renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

camera.position.set(0.3, 0.3, 0.5);

const controls = new OrbitControls(camera, renderer.domElement);

// scene.background = new THREE.Color(0.6, 0.6, 0.6);

// const ambientLight = new THREE.AmbientLight(0xffffff, 0.2);
// scene.add(ambientLight);

const directionLight = new THREE.DirectionalLight(0xffffff, 0.4);
scene.add(directionLight);

// const boxGeometry = new THREE.BoxGeometry(1,1,1);
// const boxMaterial = new THREE.MeshBasicMaterial({color: 0x00ff00});
// const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
// scene.add(boxMesh);

let donuts;
new GLTFLoader().load('../resources/models/donuts.glb', (gltf) => {console.log(gltf);
    scene.add(gltf.scene);
    donuts = gltf.scene;

    // gltf.scene.traverse((child)=>{//     console.log(child.name);
    // })

    mixer = new THREE.AnimationMixer(gltf.scene);
    const clips = gltf.animations; // 播放所有动画
    clips.forEach(function (clip) {const action = mixer.clipAction(clip);
        action.loop = THREE.LoopOnce;
        // 停在最初一帧
        action.clampWhenFinished = true;
        action.play();});

})

new RGBELoader()
    .load('../resources/sky.hdr', function (texture) {
        scene.background = texture;
        texture.mapping = THREE.EquirectangularReflectionMapping;
        scene.environment = texture;
        renderer.outputEncoding = THREE.sRGBEncoding;
        renderer.render(scene, camera);
});

function animate() {requestAnimationFrame(animate);

    renderer.render(scene, camera);

    controls.update();

    if (donuts){donuts.rotation.y += 0.01;}

    if (mixer) {mixer.update(0.02);
    }
}

animate();

(4)执行 npm run start,关上 http://localhost:3000/

成绩展现

结束语

尽管这个案例比较简单,然而它可能让咱们理解程序开发和美术资源是如何合作的,咱们能够学习到 3D 模型如何在 Threejs 中被应用,置信可能帮忙大家关上 Threejs 的大门。当然胖达老师前面的课程中有讲到更为简单的元宇宙场景如何实现,以及如何载入人物模型管制其静止,更加可能激发大家的趣味,当前有空再和大家分享。

正文完
 0