先去下载代码,它的地址是: github.com/mrdoob/thre… 可以用script引用

<script src="https://wow.techbrood.com/libs/three.r73.js"></script>

在Three.js中要渲染物体到网页中我们需要3个组件

场景scene

场景是所有物体的容器,如果要显示一个苹果,就需要将苹果对象加入场景中

let scene = new THREE.Scene();

相机camera

另一个组建是相机,相机决定了场景中那个角度的景色会显示出来。相机就像人的眼睛一样,人站在不同位置,抬头或者低头都能够看到不同的景色。 场景只有一种,但是相机却有很多种 只要设置不同的相机参数,就能够让相机产生不一样的效果

透视相机这里使用的是透视相机

let camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000)

设置不同的相机需要不同的参数 会出现不同的效果

渲染器renderer

渲染器决定了渲染的结果应该画在页面的什么元素上面 并且以怎样的方式来绘制

let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
//挂载到页面
document.body.appendChild(renderer.domElement)
let geometry = new THREE.CubeGeometry(1, 1, 1);
//width:立方体x轴的长度,height:立方体y轴的长度,depth:立方体z轴的长度也是深度
renderer.render(scene, camera)
//scene:前面定义的场景,camera:前面定义的相机
//renderTarget:渲染的目标默认是是渲染到前面定义的render变量中
//forceClear:每次绘制之前都将画布的内容给清除,即使自动清除标志autoClear为false,也会清除
function render() {
    cube.rotation.x += 0.1
    cube.rotation.y += 0.1
    renderer.render(scene, camera)
    requestAnimationFrame(render)

模型操作:

生成几何体 => 生成材质 => 混合生成模型 商城模型 => 添加到场景中

生成场景(配置参数...) => 模型导入场景

生成相机 = > 添加控制器(控制相机)

渲染器操作

生成渲染器 => 场景和相机添加到渲染器中 => 建立和canvas 关联

更新模块(动画模块)

动画的连续 ,相机 ,场景的更新控制

案例演示 :创建一个简单的立方体

three.js 里面的颜色是 new THREE.Color()

简单的控制相机

//真是世界的相机 : 近大远小
const camera = new THREE.PerspectiveCamera(75, width / height, 0.01, 1000);
//摆放向机的位置 相机的朝向
camera.position.z = 6;camera.lookAt(0, 0, 0);
//简单的控制相机
const control = new THREE.OrbitControls(camera);

创建好后在动画渲染里面更新控制器

//更新控制器
control.update();

案例演示 点击拖动: 简单的控制相机

常见的几何体 Geometry

生成一个辅助网格体 就是带有辅助线的立方体 THREE.WireframeGeometry

THREE.BoxGeometry : 立体矩形

​ 构造函数: 前面三个参数(x, y, z)默认1 ​ 后面还有三个参数(每个面的分段)

THREE.CircleGeometry : 圆

//创建圆形  CircleGeometry: 半径 分段 第一个分段的起始角度 旋转角度/弧度
//分段越多越像圆
const geometry = new THREE.CircleGeometry(3,30,Math.PI * 2)

THREE.CylinderGeometry : 圆柱

//创建圆柱  CylinderGeometry : 顶部半径  底部半径  高
const geometry = new THREE.CylinderGeometry(2,2,5);

THREE.ConeGeometry : 圆锥

//圆锥 ConeGeometry : 底面半径 高
const geometry = new THREE.ConeGeometry(2,5);

THREE.DodecahedronGeometry :十二面几何体(球)

//十二面几何体 DodecahedronGeometry :半径 第二个参数越大越接近球
const geometry = new THREE.DodecahedronGeometry(2,2);

PlaneGeometry 平面几何体 (重要)生成底面

//平面几何体 生成底面 PlaneGeometry : 宽 高 宽分段 高分段
const geometry = new THREE.PlaneGeometry(10,10,30,30);

RingGeometry 平面圆环几何体

//圆环几何体 RingGeometry : 内部半径 外部半径 圆的分段数越大越圆  圆环表面的分段数
const geometry = new THREE.RingGeometry(2,5,20,8);

TorusGeometry :圆环几何体

//圆环几何体 TorusGeometry : 圆环的半径  管道的半径 圆环的分段 管道的分段越多越圆
const geometry = new THREE.TorusGeometry( 4,1,10,20 );

案例演示: 常见的几何体

自定义几何体

  • 必须要有端点(定义制作)
  • 必须要有面(三点形成一个面 手动添加面的关联)
  • 建立一个坐标系 AxesHelper

    //建立一个简单的坐标系 坐标系的长度
    const axesHelper = new THREE.AxesHelper(5);
    scene.add( axesHelper );
    

    创建自定义

    描述一个点 THREE.Vector3() 描述一个面 THREE.Faces()

    //生成Geometry的实例
    const geometry = new THREE.Geometry();
    //添加点
    geometry.vertices.push(new THREE.Vector3(1,0,0));
    geometry.vertices.push(new THREE.Vector3(0,1,0));
    geometry.vertices.push(new THREE.Vector3(0,0,1));
    //根据这些点确定一个面
    geometry.faces.push(new THREE.Face3(0,1,2, normal, color));
    

    创建点可以写坐标 也可以写极坐标 Vector3().applyEuler 参数里面要生成一个欧拉角 Euler

    geometry.vertices.push(new THREE.Vector3(5,0,0).applyEuler(new THREE.Euler(0,0,1,'XYZ')));//参数 前三个是根据多少值 旋转 对应 XYZ
    

    案例演示: 自定义几何体

    几何体组合

    Object3D 实例对象内部可以存放多个mesh ,每个mesh都是独立控制的

    THREE.Object3D

    let obj = new THREE.Object3D();
    //模型对象添加子模型
    obj.add(mesh1);
    obj.add(mesh2);
    //模型对象添加到场景中
    scene.add(obj);
    

    案例演示 :小案例

    LineBasicMaterial() 基础线条

    /生成Geometry的实例
    const geometry = new THREE.Geometry();
    //添加关键点
    geometry.vertices.push(new THREE.Vector3(1,1,1));
    geometry.vertices.push(new THREE.Vector3(3,3,3));
    //将线条按顺序连接起来
    const material = new THREE.LineBasicMaterial();
    new THREE.Line(geometry,material)
    

    线条渐变色

    //生成Geometry的实例
    const geometry = new THREE.Geometry();
    //添加关键点
    geometry.vertices.push(new THREE.Vector3(1,1,1));
    geometry.vertices.push(new THREE.Vector3(3,3,3));
    geometry.vertices.push(new THREE.Vector3(5,3,2));
    geometry.colors.push(
        new THREE.Color(0xff0000),
        new THREE.Color(0x0000ff)
    //线条是被点来进行染色的
    const material = new THREE.LineBasicMaterial({  vertexColors:true});
    new THREE.Line(geometry,material)
    

    案例演示: 线的绘画

    法线网格材质(初学) MeshNormalMaterial

    物体内部有光

    const material = new THREE.MeshNormalMaterial({  
        //内部也有光  
        side:THREE.DoubleSide
    

    基础网格材质 MeshBasicMaterial

    一个以简单着色(平面或线框)方式来绘制几何体的材质。 基础材质可以进行贴图

    new THREE.MeshNormalMaterial({side:THREE.DoubleSide})
    //wireframe 显示线条
    const material = new THREE.MeshNormalMaterial({
        side:THREE.DoubleSide,
        wireframe:true
    const geometry = new THREE.BoxGeometry( 2, 2, 2, 2, 2, 2);
    const mesh = new THREE.Mesh( geometry, material );
    mesh.position.x = index * 3 - meshList.length;
    scene.add(mesh);
    

    可以载入纹理

    Lambert网格材质MeshLambertMaterial

    一种非光泽表面的材质,没有镜面高光。

    new THREE.MeshLambertMaterial({map:texture})
    //flatShading 每一个面接受光照
    new THREE.MeshLambertMaterial({map:texture,flatShading:true})
    

    Phong网格材质 MeshPhongMaterial

    具有镜面高光的光泽表面的材质

    new THREE.MeshPhongMaterial({flatShading:true,envMap:scene.background})
    //envMap 环境贴图
    

    卡通网格材质 MeshToonMaterial

    new THREE.MeshToonMaterial({map:texture,side:THREE.DoubleSide})
    

    案例演示: 材质

    纹理和材质

    纹理 : 本质是一张图片或者Canvas ,或视频 材质: 包含了贴图的纹理 ,相当于实际物体的质感, 物体在场景中的表现

    纹理(texture)

    需要引入贴图 , 加载纹理贴图到物体表面, 或者是作为镜面反射或折射的贴图

    简单的纹理引入 : TextureLoader

    //引入纹理
    //创建纹理引入工具
    const loader = new THREE.TextureLoader();
    const texture = loader.load("图片地址");
    const material = new THREE.MeshBasicMaterial({
        map:texture,
        side:THREE.DoubleSide
    

    例如下面这个案例 案例演示 : 几何体的纹理

    盒子世界纹理引入 CubeTextureLoader

    const loader = new THREE.CubeTextureLoader();
    //场景引入
    scene.background = loader.setPath( '../lib/textures/cube/Park3Med/' )    
        .load( [
        'px.jpg','nx.jpg',      
        'py.jpg','ny.jpg',      
        'pz.jpg','nz.jpg'
    

    例如下面这个案例 案例演示 : 世界纹理

    PerspectiveCamera 透视相机(近大远小)

    //透视相机 近大远小 :垂直视野角度  锥体长宽比  物体近端面 物体远端面
    const camera = new THREE.PerspectiveCamera(75, width / height, 0.01, 1000);//摆放向机的位置 相机的朝向
    camera.position.z = 10;
    //看向哪里
    camera.lookAt(0, 0, 0);
    

    OrthographicCamera 正交相机

    环境光 AmbientLight

    没有一个固定光源的时候, 周围的物体会根据环境折射光线 不能投射阴影

    //环境光的颜色  光照强度
    const ambientLight = new THREE.AmbientLight( 0xffffff, 0.3 );
    scene.add( ambientLight );
    

    点光源 PointLight

    //十六进制光照颜色  光照强度  从光源到光照强度为0的位置
    const light2 = new THREE.PointLight( 0xffffff, 1, 1000 );
    //设置位置
    light2.position.set( 0, 8, 8 );
    scene.add( light2 );
    

    点光源辅助线THREE.PointLightHelper

    平行光 DirectionalLight

    //两个参数 光的颜色及其光照强度
    const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
    scene.add( directionalLight );
    

    DirectionalLightHelper 平行光的辅助线

    半球光 HemisphereLight

    模拟日出日落 不能投射阴影

    const hemisphereLight = new THREE.HemisphereLight( 0xffffff, 0x000000, 1 );
    scene.add( hemisphereLight );
    

    聚光灯 SpotLight

    //灯光的颜色
    const spotLight = new THREE.SpotLight( 0xffffff );
    spotLight.position.set( 0, 10, 0 );
    //聚光灯的弧度大小
    spotLight.angle = Math.PI/6;
    scene.add( spotLight );
    

    平面光光源 RectAreaLight

    从一个矩形平面上均匀地发射光线 不支持阴影

    //颜色  强度 宽度 高度
    const rectLight = new THREE.RectAreaLight( 0xffffff, 1,  10, 10 );
    rectLight.position.set( 5, 5, 0 );
    rectLight.lookAt( 0, 0, 0 );
    scene.add( rectLight );
    

    特殊的光源 比如 点光源 聚光灯 必须有 产生阴影的物体 必须要有 显示(接收)阴影的物体

    灯光照射产生阴影

    const spotLight = new THREE.SpotLight( 0xffffff );//聚光灯
    spotLight.position.set( 0, 10, 0 );
    spotLight.angle = Math.PI/6;
    this.spot.castShadow = true;//照射产生阴影
    scene.add( spotLight );
    

    物体要产生阴影

    const geometry =new THREE.BoxGeometry(3, 3, 3);
    const material = new THREE.MeshLambertMaterial({
        color:new THREE.Color(0xffffff),
        side:THREE.DoubleSide,
        map:new THREE.TextureLoader().load('图片地址')
    const mesh = new THREE.Mesh(geometry,material);
    scene.add(mesh);
    //物体产生阴影
    mesh.castShadow = true;
    

    底面接收阴影

    const geometry = new THREE.PlaneGeometry(100,100,10,10);
    const material = new THREE.MeshPhongMaterial({
        color: 0xeeeeee,
        side: THREE.DoubleSide
    const mesh = new THREE.Mesh(geometry,material);
    //旋转90度
    mesh.rotateX(- Math.PI / 2);
    mesh.position.set(0, -5 ,0);
    scene.add(mesh);
    //接收阴影
    mesh.receiveShadow = true;
    

    产生阴影要开启阴影模式

    renderer.shadowMap.enabled = true;
    

    加载方式是一个异步加载: 使用回调函数添加到场景当中

    GLTFLoader 加载器

    const loader = new THREE.GLTFLoader()//获取加载器的实例方法
    //path/to/sourse 资源的加载地址
    loader.load("path/to/sourse",res=>{
        //res 是加载的资源
        //res.scene是模型的场景
        scene.add(res.scene)
        //res的材质十多个面
        //数组遍历每一个面设置不同的反光效果
        //res.scene.traverse 相当于 res.scene是一个数组, 遍历数组的每一个面设置不同的反光
        res.scene.traverse(mesh=>{
            if (mesh.isMesh){
                //观看模型的内部
                mesh.material.side = THREE.BackSide
                //背景对所有的面进行一一映射
                mesh.material.envMap = scene.background;
    

    MMDLoader 加载器

    const loader = new THREE.MMDLoader();
    loader.load('pmd后缀的文件',mesh=>{
        //调整位置
        mesh.position.set(0,-10,0)
        scene.add(mesh);
    

    MMD 动画效果

    需要引入AMMO 物理引擎 MMDAnimationHelper 动画效果

    //需要一个pmd后缀文件和vmd后缀文件
    const helper = new THREE.MMDAnimationHelper();
    const loader = new THREE.MMDLoader();
    loader.loadWithAnimation(
        'pmd后缀文件',
        'vmd后缀文件',
        mmd => {
            helper.add(mmd.mesh, {
                animation: mmd.animation,
                physics: true
            scene.add( mmd.mesh );
    //在动画渲染的地方写上
    //动画实时渲染
    const clock = new THREE.Clock();
    helper.update(clock.getDelta());
    

    镜面效果Reflector

    import {Reflector} from "three/examples/jsm/objects/Reflector";
    const geometry = new THREE.PlaneGeometry(10,10);
    //设置镜子材质
    const mirrorMesh = new Reflector(geometry,{
        color:new THREE.Color(0x7f7f7f)//镜子的颜色
    //设置位置
    mirrorMesh.position.set(0,0,-5);
    //镜子的朝向
    mirrorMesh.lookAt(0,0,0)
    

    拖拽控制 OrbitControls

    //传入相机和控制的标签
    let control = new OrbitControls(camera,renderer.domElement);
    control.enabled = true//禁止事件
    //在动画里渲染
    control.update();
    

    进阶拖拽控制器 TrackballControls

    let control = new TrackballControls(camera,renderer.domElement);
    control.noPan = true//禁止平移
    control.noZoom = true//是否允许放大
    control.noRotate = true//禁止拖拽
    control.rotateSpeed = 5//拖拽的速度
    control.zoomSpeed = 5//滚轮的速度
    control.panSpeed = 5//平移的速度
    //在动画里渲染
    control.update();
    

    飞行控制器 FlyControls

    let control = new FlyControls(camera,renderer.domElement);
    control.movementSpeed = 10;//移动的速度
    control.rollSpeed = 3;//平移旋转速度
    control.autoForward = true;//自动飞行
    control.dragToLook = true;//拖拽调整方向
    //在动画里渲染 需要传入一个时间的参数
    const clock = new THREE.Clock()
    control.update(clock.getDelta());
    

    第一人称控制器FirstPersonControls

    let control = new FirstPersonControls(camera,renderer.domElement);
    control.lookSpeed = 0.15//鼠标移动速度 默认值 0.001
    control.movementSpeed = 10//移动速度 默认值 1
    //在动画里渲染 需要传入一个时间的参数
    const clock = new THREE.Clock()
    control.update(clock.getDelta());
    

    锁定鼠标控制器 PointerLockControls

    3D游戏的最佳选择

    let control = new PointerLockControls(camera,renderer.domElement);
    //需要锁定指针 
    canvas.addEventListener("click",()=>{
        control.lock()
    //监听lock事件
    controls.addEventListener( 'lock',  ()=> {
    	//锁定指针
    controls.addEventListener( 'unlock',  ()=> {
    	//没有锁定指针
    复制代码
  •