当前位置: 首页 > 工具软件 > Victor.js > 使用案例 >

THREE.js学习笔记

潘星阑
2023-12-01

1.引入THREE.js文件

1.在body下引入THREE.js

// 根据自己的路径写src,js文件在build 文件夹下
<script src="../three.js-r102/build/three.js"></script> 
<script>
	// 在这创建场景
</script>

2.设置style

	body {margin :0;}
	canvas {width: 100%;height: 100%;}

2.创建初始场景

一个渲染场景需要的三大件:场景、相机、渲染器,这样我们就能透过摄像机渲染出场景。

<script>
	// 创建 场景 相机 渲染器
	var scene, renderer, camera;
     // 创建场景
    function createScene() {
   		scene = new THREE.Scene();
    }
    // 创建相机
    function createCamera() {
   		// PerspectiveCamera(视野角度, 长宽比, 近切面, 远切面)
    	camera = new THREE.PerspectiveCamera(75, window.innerWidth/innerHeight, 0.1, 1000);
    	// 设置相机的位置方法 camera.position.set(x, y, z)
    	camera.position.set(0, 0, 15);
    	// 设置相机的焦点
    	camera.lookAt(0,0,0);
    }
    // 创建渲染器
    function createRenderer() {
    	renderer = new THREE.WebGLRender();
    	renderer.setSize(window.innerWidth, window.innerHeight);
    	document.body.appendChild(renderer.domElement);
    }
</script>

3.创建物体和动画

THREE.js内置了两种几何体类型,Geometry(普通几何体)BufferGeometry(缓冲类型几何体),它们两个的区别是:BufferGeometry存储的都是一些原始的数据,性能比Geometry的性能高,很适合存储一些放入场景内不需要再额外操作的模型。而Geometry的优势刚好相反,Geometry比BufferGeometry更友好,使用了Three.js提供的THREE.Vector3或者THREE.Color这样的对象来存储数据(顶点位置,面,颜色等),这些对象易于阅读和编辑,但效率低于BufferGeometry使用的类型化数组。
所以,我们可以根据项目的大小来使用不同的几何体,小项目,可以使用Geometry实现,中大型的项目,还是推荐BufferGeometry

  • 1.Geometry 和 BufferGeometry 互转
    • BufferGeometry 转换成 Geometry
    //实例化一个Geometry对象
    var geo = new THREE.Geometry(); 
    //调用对象的fromBufferGeometry方法,并将需要转换的bufferGeometry传入
    geo.fromBufferGeometry(bufferGeometry);
    //geo为转换转换成的Geometry
    
    • Geometry 转换成 BufferGeometry
    //实例化一个BufferGeometry对象
    var bufferGeo = new THREE.BufferGeometry(); 
    //调用对象的fromGeometry方法,并将需要转换的Geometry传入
    bufferGeo.fromGeometry(geometry);
    //bufferGeo为geometry转换转换成的BufferGeometry
    
  • 2.创建物体和动画
    		 // 创建立方体
            var geometry, material, cube;
            function createGeometry() {
            	// new THREE.BoxGeometry(宽, 高, 深, [沿宽度的分隔面的数量], [沿高度的分隔面的数量], [沿深度的分隔面的数量])
            	// 创建一个几何体
                geometry = new THREE.BoxGeometry(5, 10, 15);
                // 创建一个材质
                material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
                // 模型 = 几何体 + 材质
                cube = new THREE.Mesh(geometry, material);
                // 物体默认坐标 (0,0,0)
                scene.add(cube);
            }
            // 创建动画
            function animate() {
            // requestAnimatinFrame(); 请求动画帧 API
                requestAnimationFrame(animate);
                cube.rotation.x += 0.01;
                cube.rotation.y += 0.02;
                // 渲染场景
                renderer.render(scene, camera);
            }
    
  • 3.一般几何体
    // 1.圆形平面
    var circle = new THREE.CircleGeometry(5, 32);
    	// 构造函数
    	CircleGeometry(半径, 段数, [第一段起始角度], [圆形扇形的中心角])
    // 2.圆锥
    var cone= new THREE.ConeGeometry(5,10,32);
    	// 构造函数
    	ConeGeometry(半径, 圆锥高度, [圆锥表面的段数,越高越圆滑], [高度方向的段数],[底部显示或隐藏,默认是false-显示], [第一段的起始角度], [中心角,默认是2*PI]]);
    // 3.圆柱
    var cylinder = new THREE.CylinderGeometry();
    	// 构造函数
    	CylinderGeometry(顶部圆柱体半径, 底部圆柱体半径, 高度, [圆柱表面分段数], [高度分段数], [圆柱体两端是否显示], [第一段的起始角度], [中心角,默认是2*PI] );
    // 4.球
    var sphere = new THREE.SphereGeometry(5,32,32);
    	// 构造函数
    	SphereGeometry(半径, 水平线段数量, 垂直段的数量, [水平起始角度],[水平角度大小], [垂直起始角度], [垂直角度大小]);
    // 5.平面
    var plane = new THREE.PlaneGeometry(5,10,32);
    	// 构造函数
    	PlaneGeometry(宽度, 长度, [宽的分段数], [长度的分段数])
    // 6.圆环
    var torus = new THREE.TorusGeometry(10,5);
    	// 构造函数
    	ToursGeometry(圆环半径, 管道半径, [横向分段,,默认8], [纵向分段,默认6], [绘制弧度,默认2*PI])
    
  • 4.线条
    • 1.线条用的材质只有LineBasicMaterial 或者 LineDashedMaterial
    • 2.定义带有一些顶点的Geometry 或者 BufferGeometry,这里使用Geometry。
    	    // 创建线条
            var geometry, material, line;
            function createGeometry() {
                geometry = new THREE.Geometry();
                // 创建顶点
                // 线是画在每一对连续的顶点之间的,而不是在第一个顶点和最后一个顶点之间绘制线条(线条并未闭合)
                geometry.vertices.push(new THREE.Vector3(-10, 0, 0));
                geometry.vertices.push(new THREE.Vector3(0, 10, 0));
                geometry.vertices.push(new THREE.Vector3(10, 0, 0));
                geometry.vertices.push(new THREE.Vector3(20, 30, 10));
                material1 = new THREE.LineDashedMaterial({
                    color: 0x0000ff
                });
                line = new THREE.Line(geometry1, material1);
                scene.add(line);
            }
    
  • 5.常用方法
    • 1.geometry.center();
      • 居中方法
    • 2.geometry.dispose()
      • 将几何体从内存中删除

4.材质

  • 1.material的基本属性和方法
    • 1.material.needsUpdate
      • 如果修改了Material内的内容,需要将此属性设置为true,然后Three.js会在下一帧里面将修改内容同步到WebGL的显存内。只需要在更新Material属性后设置一次即可
    • 2.material.map
      • 此属性可以配置当前材质的纹理贴图,是一个THREE.Texture对象
    • 3.material.wireframe
      • 是否将模型渲染成线框,默认为false
    • 4.material.dispose()
      • 此方法用于将材质从内存中删除,在不需要使用当前材质时使用,但不会将材质的纹理贴图删除,如果需要将纹理贴图也删除,需要调用material.map.dispose()
  • 2.配置纹理贴图
    • 使用 THREE.TextureLoader 生成纹理
    var texture = new THREE.TextureLoader().load( "文件路径" ); 
    material.map = texture; //将纹理赋值给材质
    
    • 纹理的重复
    texture.wrapS = THREE.RepeatWrapping; //设置水平方向无限循环
    texture.wrapT = THREE.RepeatWrapping; //设置垂直方向无限循环
    // 设置纹理的重复
    texture.repeat.set( 4, 4 ); //水平方向和垂直方向都重复四次
    

5.内置常用材质

  • 1.基础材质MeshBasicMaterial
    var material = new THREE.MeshBasicMaterial({color:0x00ffff});
    // 可以修改材质的颜色,方法一
    material.color.set(0xff00ff)
    // 方法二:修改材质的颜色,支持十六进制数,字符串,RGB字符串,颜色字符串,HSL字符串,
    material.color = new THREE.Color("#ff0000")
    var geometry = new THREE.BoxGeometry(1, 1, 1);
    var mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);
    
  • 2.法线材质 MeshNormalMaterial
    • 会根据面的方向不同自动改变颜色,不受灯光影响
    material = new THREE.MeshNormalMaterial();
    
  • 3.线条材质 LineBasicMaterial
    lineMaterial = new THREE.LineBasicMaterial({color:0x00ff00}); // 线条材质
    
  • 4.虚线材质 LineDashedMaterial
    var pointsArr = [
        new THREE.Vector3( -10, 0, -5 ),
        new THREE.Vector3( -5, 15, 5 ),
        new THREE.Vector3( 20, 15, -5 ),
        new THREE.Vector3( 10, 0, 5 )
    ];
    //指定一些用于生成曲线线的三维顶点
    var curve = new THREE.CatmullRomCurve3(pointsArr);
    var points = curve.getPoints( 50 ); //使用getPoints获取当前曲线分成50段后的所有顶点
    var curveGeometry = new THREE.BufferGeometry().setFromPoints( points ); //使用顶点生成几何体
    var curveMaterial = new THREE.LineDashedMaterial( { color : 0xff0000 } ); //创建一条红色的线材质
    // 使用THREE.Line创建线
    curveLine = new THREE.Line( curveGeometry, curveMaterial );
    curveLine.computeLineDistances(); //需要重新计算位置才能显示出虚线
    scene.add(curveLine);
    
  • 5.兰伯特材质 MeshLambertMaterial
    material = new THREE.MeshLambertMaterial({color:0x00ffff});
    
  • 6.高光材质 MeshPhongMaterial
    material = new THREE.MeshPhongMaterial({color:0x00ffff}); //创建材质
    // 属性: 高光颜色:material.specular 高光贴图: material.specularMap
    
  • 7.PBR材质 MeshStandardMaterial
    material = new THREE.MeshStandardMaterial({color:0x00ffff}); //创建材质
    /*
    	属性:
    	金属度:material.metalness  金属贴图:material.metalnessMap
    	粗糙度: material.roughness  粗糙度贴图: material.roughnessMap	
    */ 
    

6.引入外部文件存在的问题

倘若需要从外部文件里载入几何体或是纹理贴图,由于浏览器same origin policy(同源策略)的安全限制,从本地文件系统载入外部文件将会失败,同时抛出安全性异常。
解决方法:
在本地的服务器运行文件

	http://localhost/文件地址

7.Light 灯光

  • 1.灯光种类

    • 环境光–AmbientLight()
      • 不产生阴影,接受两个值,颜色和强度
    var light = new THREE.AmbientLight(0x00ffff);
    scene.add(light);
    
    • 平行光–DirectionalLight()
      • 模拟太阳光,接受两个值,颜色和强度
    var light = new THREE.DirectionalLight(0x00ffff, 1.5);
    // 设置灯光的 颜色 强度 位置 朝向
    light.color.set(0xff00ff); // 设置颜色
    light.intensity = 1.2; // 设置强度
    light.position.set(10, 10, 10); // 设置位置
    light.target.set(10, 0, 0) // 设置目标点
    scene.add(light);
    
    • 点光源:PointLight(),有衰减
      • 四个参数:颜色、强度、[照射范围,不写的话是所有物体受光源影响]、[衰减度,默认是1]
    var pointLight = new THREE.PointLight(0xff0000, 1, 100, 2); // 创建一个白色的点光源
    pointLight.position.set( 50, 50, 50 );
    // 设置灯光衰减
    pointLight.decay = 1.0 // 设置衰减
    scene.add( pointLight );
    
    • 聚光灯:SpotLight()
    • 六个参数: 颜色 强度 光照范围 椎体角度 交界处的过渡 衰减度
    var spotLight = new THREE.SpotLight(0xffffff, 2.0, 100, Math.PI/4, 0.5, 2);
    spotLight.color.set(0x000000); // 修改光照颜色
    spotLight.intensity = 0.5; // 修改光的强度
    spotLight.distance = 50; // 修改光的照射范围
    spotLight.angle = Math.PI/3; // 修改光的照射弧度
    spotLight.penumbra = 1.0; // 修改交界过渡
    spotLight.decay = 1.0; // 修改衰减度
    spotLight.target.set(0, 1, 1); // 修改照射方向
    
    • 室外光源: HemisphereLight
      • 三个参数: 天空颜色 地面颜色 光的强度
    var hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
    hemisphereLight.color.set(0xffffff); //将天空颜色修改为白色
    hemisphereLight.groundColor.set(0x000000); //将地面颜色修改为黑色
    scene.add(hemisphereLight);
    
  • 2.添加阴影效果

    • 1.设置 渲染器产生阴影
    	renderer.shadowMap.enabled = true;
    
    • 2.设置 灯光渲染阴影
    var light = new THREE.DirectionalLight("#ffffff");
    light.castShadow = true; // 设置平行光投射投影
    scene.add(directionalLight);
    
    • 3.设置 哪些模型可以产生阴影,哪些模型接受阴影
      • 物体开启灯光:geometry.castShadow = true;
      • 物体接受灯光:geometry.receiveShadow = true;
    sphere.castShadow = true; // 圆球产生阴影
    scene.add(sphere);
    cube.castShadow = true; // 立方体产生阴影
    scene.add(cube);
    plane.receiveShadow = true; // 平面接收阴影
    scene.add(plane);
    
    • 4.设置何时的阴影渲染范围和密度
    directionalLight.shadow.camera.near = 20; // 产生阴影的最近距离
    directionalLight.shadow.camera.far = 100; // 产生阴影的最远距离
    directionalLight.shadow.camera.left = -50; // 产生阴影距离位置的最左边位置
    directionalLight.shadow.camera.right = 50; // 最右边
    directionalLight.shadow.camera.top = 50; // 最上边
    directionalLight.shadow.camera.bottom = -50; // 最下面
    
    //这两个值决定生成阴影密度 默认512
    directionalLight.shadow.mapSize.height = 1024;
    directionalLight.shadow.mapSize.width = 1024;
    

8.相机Camera

  • 1.常用的相机有 正交相机(OrthographicCamera)和透视相机(PerspectiveCamera)两种相机,用于来捕获场景内显示的物体模型。
    • 1.相机的属性和方法
      • 1.朝向目标点
        • camera.target 属性
        • camera.lookAt() 方法
    	// 相机朝向原点
    	camera.target = new THREE.Vector3(0, 0, 0);
    	// 或者
    	camera.lookAt(new THREE.Victor3(0, 0, 0));
    
    • 2.朝向 物体
    		var mesh = new THREE.Mesh(geometry, material);
    		camera.target = mesh.position;
    		//或者
    		camera.lookAt(mesh.position);
    
  • 2.正交相机(相当于正视图)
    + 通过top,left,right,bottom,near和far六个值确定渲染范围
    var orthographicCamera = new THREE.OrthograthicCamera(-5, 5, -4,4,8,-8)
    // 相机显示的内容需要和窗口显示的内容同样的比例才能不被拉伸
    var frustumSize = 1000; // 设置显示相机前方1000高的内容
    var aspect = window.innerWidth / window.innerHeight; //计算场景的宽高比
    var orthographicCamera = new THREE.OrthographicCamera( frustumSize * aspect / 5, frustumSize * aspect / -5, frustumSize / -4, frustumSize / 4, 1, 2000 ); // 根据比例计算出left,top,right,bottom的值
    
    • 动态设置 正交相机的属性
    var frustumSize = 1000; //设置显示相机前方1000高的内容
    var aspect = window.innerWidth / window.innerHeight; //计算场景的宽高比
    var orthographicCamera = new THREE.OrthographicCamera(); //实例化一个空的正交相机
    orthographicCamera.left = frustumSize * aspect / - 2; //设置left的值
    orthographicCamera.right = frustumSize * aspect / 2; //设置right的值
    orthographicCamera.top = frustumSize / 2; //设置top的值
    orthographicCamera.bottom = frustumSize / - 2; //设置bottom的值
    orthographicCamera.near = 1; //设置near的值
    orthographicCamera.far = 2000; //设置far的值
    //注意,最后一定要调用updateProjectionMatrix()方法更新
    
 类似资料: