2022-04-07 来源:华纳网 责任编辑:谷雨 人气:
核心提示:知识点: Three.js基础知识

知识点:

Three.js基础知识


 

本课内容:

大家好,欢迎来到谷雨课堂,

往期的课程,

我们讲过物联网的相关开发,

以及3D程序即Unity的基础安装与使用,

那么本节,

我们来讲一下基础网页的3D开发,

Three.js

 

在互联网发展有今天,

前端技术飞跃发展,

放眼望去,

几乎没有什么是前端H5技术办不到的了,

连C、Golang都可以编译成wasm进行开发了,

JS虚拟机都可以搞虚拟机了

 

那么基于WebGL的3D应用,

对于WEB来讲,

 

当然是不在话下了,
 


 

相关部分代码(来自于Example)

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
import * as THREE from 'three';import { TrackballControls } from './jsm/controls/TrackballControls.js';import Stats from './jsm/libs/stats.module.js';import { GUI } from './jsm/libs/lil-gui.module.min.js';
import { GLTFLoader } from './jsm/loaders/GLTFLoader.js';
let container, stats, clock, gui, mixer, actions, activeAction, previousAction;let camera, scene, renderer, model, face;let controls;
const api = { state: 'Walking' };
      init();      animate();
function init() {
        container = document.createElement( 'div' );document.body.appendChild( container );
        camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 0.25, 100 );        camera.position.set( - 5, 3, 10 );        camera.lookAt( new THREE.Vector3( 0, 2, 0 ) );
        scene = new THREE.Scene();        scene.background = new THREE.Color( 0xe0e0e0 );        scene.fog = new THREE.Fog( 0xe0e0e0, 20, 100 );
        clock = new THREE.Clock();
// lights
const hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );        hemiLight.position.set( 0, 20, 0 );        scene.add( hemiLight );
const dirLight = new THREE.DirectionalLight( 0xffffff );        dirLight.position.set( 0, 20, 10 );        scene.add( dirLight );
// ground
const mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2000, 2000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );        mesh.rotation.x = - Math.PI / 2;        scene.add( mesh );
const grid = new THREE.GridHelper( 200, 40, 0x000000, 0x000000 );        grid.material.opacity = 0.2;        grid.material.transparent = true;        scene.add( grid );
// model
const loader = new GLTFLoader();        loader.load( 'models/gltf/RobotExpressive/RobotExpressive.glb', function ( gltf ) {
console.log(gltf)          model = gltf.scene;          scene.add( model );
          createGUI( model, gltf.animations );
        }, undefined, function ( e ) {
console.error( e );
        } );
        renderer = new THREE.WebGLRenderer( { antialias: true } );        renderer.setPixelRatio( window.devicePixelRatio );        renderer.setSize( window.innerWidth, window.innerHeight );        renderer.outputEncoding = THREE.sRGBEncoding;        container.appendChild( renderer.domElement );
window.addEventListener( 'resize', onWindowResize );
// stats        stats = new Stats();        container.appendChild( stats.dom );
                controls = new TrackballControls( camera, renderer.domElement );
      }
function createGUI( model, animations ) {
const states = [ 'Idle', 'Walking', 'Running', 'Dance', 'Death', 'Sitting', 'Standing' ];const emotes = [ 'Jump', 'Yes', 'No', 'Wave', 'Punch', 'ThumbsUp' ];
        gui = new GUI();
        mixer = new THREE.AnimationMixer( model );
        actions = {};
for ( let i = 0; i < animations.length; i ++ ) {
const clip = animations[ i ];const action = mixer.clipAction( clip );          actions[ clip.name ] = action;
if ( emotes.indexOf( clip.name ) >= 0 || states.indexOf( clip.name ) >= 4 ) {
            action.clampWhenFinished = true;            action.loop = THREE.LoopOnce;
          }
        }
// states
const statesFolder = gui.addFolder( 'States' );
const clipCtrl = statesFolder.add( api, 'state' ).options( states );
        clipCtrl.onChange( function () {
          fadeToAction( api.state, 0.5 );
        } );
        statesFolder.open();
// emotes
const emoteFolder = gui.addFolder( 'Emotes' );
function createEmoteCallback( name ) {
          api[ name ] = function () {
            fadeToAction( name, 0.2 );
            mixer.addEventListener( 'finished', restoreState );
          };
          emoteFolder.add( api, name );
        }
function restoreState() {
          mixer.removeEventListener( 'finished', restoreState );
          fadeToAction( api.state, 0.2 );
        }
for ( let i = 0; i < emotes.length; i ++ ) {
          createEmoteCallback( emotes[ i ] );
        }
        emoteFolder.open();
// expressions
        face = model.getObjectByName( 'Head_4' );
const expressions = Object.keys( face.morphTargetDictionary );const expressionFolder = gui.addFolder( 'Expressions' );
for ( let i = 0; i < expressions.length; i ++ ) {
          expressionFolder.add( face.morphTargetInfluences, i, 0, 1, 0.01 ).name( expressions[ i ] );
        }
        activeAction = actions[ 'Walking' ];        activeAction.play();
        expressionFolder.open();
      }
function fadeToAction( name, duration ) {
        previousAction = activeAction;        activeAction = actions[ name ];
if ( previousAction !== activeAction ) {
          previousAction.fadeOut( duration );
        }
        activeAction          .reset()          .setEffectiveTimeScale( 1 )          .setEffectiveWeight( 1 )          .fadeIn( duration )          .play();
      }
function onWindowResize() {
        camera.aspect = window.innerWidth / window.innerHeight;        camera.updateProjectionMatrix();
        renderer.setSize( window.innerWidth, window.innerHeight );
      }
//
function animate() {
const dt = clock.getDelta();
if ( mixer ) mixer.update( dt );
        requestAnimationFrame( animate );                controls.update();        renderer.render( scene, camera );
        stats.update();
      }

 


 

相关部分代码(同样来自于Example)

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
var container;var camera, scene, renderer;//用于轨道控制器var orbitControls, clock, delta;
var planeMesh;
    main();    render();
//主函数function main(){//添加一个div元素        container = document.createElement('div')document.body.appendChild(container);        scene = new THREE.Scene();//创建一个新场景
//添加一个透视相机        camera = new THREE.PerspectiveCamera(30,window.innerWidth/window.innerHeight, 1, 1000);
        camera.position.set(100, 300, 100);//设置相机位置        camera.lookAt(new THREE.Vector3(0,0,0));//让相机指向原点
//渲染//antialias:true增加抗锯齿效果        renderer = new THREE.WebGLRenderer({antialias:true});        renderer.setClearColor(new THREE.Color(0x000000));//设置窗口背景颜色为黑        renderer.setSize(window.innerWidth, window.innerHeight);//设置窗口尺寸//将renderer关联到container,这个过程类似于获取canvas元素        container.appendChild(renderer.domElement);
//添加轨道控制器//新建一个轨道控制器        orbitControls = new THREE.OrbitControls(camera, renderer.domElement);        orbitControls.target = new THREE.Vector3(0, 0, 0);//控制焦点        orbitControls.autoRotate = false;//将自动旋转关闭        clock = new THREE.Clock();//用于更新轨道控制器//给场景添加光源//自然光var ambientLight = new THREE.AmbientLight( 0xff0000 );        scene.add( ambientLight );
//平行光源var directionalLight = new THREE.DirectionalLight( 0x0000ff );        directionalLight.position.set( 1, 0.75, 0.5 ).normalize();        scene.add( directionalLight );
    plane();        sphere();        cylinder();    }//创建一个平面function plane(){var planeGeo = new THREE.PlaneGeometry(100,100,10,10);//创建平面var planeMat = new THREE.MeshLambertMaterial({  //创建材料            color:0x666666,wireframe:false        });
    planeMesh = new THREE.Mesh(planeGeo, planeMat);//创建网格模型        planeMesh.position.set(0, 0, -20);//设置平面的坐标        planeMesh.rotation.x = -0.5 * Math.PI;//将平面绕X轴逆时针旋转90度        scene.add(planeMesh);//将平面添加到场景中    }

//创建一个球function sphere(){var sphereGeo = new THREE.SphereGeometry(16, 40, 40);//创建球体var sphereMat = new THREE.MeshLambertMaterial({//创建材料            color:0x0000FF,wireframe:false        });var sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);//创建球体网格模型        sphereMesh.position.set(-25, 16, 0);//设置球的坐标        scene.add(sphereMesh);//将球体添加到场景    }//创建圆柱体function cylinder(){//创建圆柱体var cylinderGeo = new THREE.CylinderGeometry(15, 15 ,40 ,40 ,40);var cylinderMat = new THREE.MeshLambertMaterial({//创建材料            color:0xFF6600,wireframe:false        });//创建圆柱体网格模型var cylinderMesh = new THREE.Mesh(cylinderGeo, cylinderMat);        cylinderMesh.position.set(0, 20, -40);//设置圆柱坐标        scene.add(cylinderMesh);//向场景添加圆柱体    }//渲染function render(){        delta = clock.getDelta();        orbitControls.update(delta);        requestAnimationFrame(render);    planeMesh.rotation.z += -0.005 * Math.PI;        renderer.render(scene, camera);    }

 

其实不仅是Three.js

就是Unity及UE这样大厂的“巨型”引擎,

也是可以发布成WEB版的,

就是我们通常看到的“手游”,

其实就是基于WebGL

 

那么我们来开发一些小型的3D应用,

如果不想安装那些大型的软件,

 

其实Three.js未尝不是一个好的选择
 


 

完整的源代码可以登录【华纳网】下载。

https://www.worldwarner.com/

 

 





免责声明:本文仅代表作者个人观点,与华纳网无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。