Three.js官方案例webgl

Three.js官方案例webgl

码农世界 2024-05-27 前端 75 次浏览 0个评论

目录

1 安装VSCode  ,并安装插件live-server

2 下载官方three.js到本地

3 学习案例webgl_materials_car

3.1 car.html部分

3.2 body部分

3.3 car.html全部脚本

3.2 car.js部分

3.2.1 加载gltf模型

3.2.2 添加灯光

3.2.3 添加环境贴图

3.2.4 添加车身材质

3.2.5 添加地面网格

3.2.6 添加动画

3.2.6 添加控制器

3.2.7 添加雾效

3.2.8 添加车的影子

3.2.9 添加监听窗口大小变化的函数

3.2.10 添加性能监视器

​3.2.11 car.js全部脚本

 4 最终效果


1 安装VSCode  ,并安装插件live-server

找到后点击安装就行。

2 下载官方three.js到本地

本机搭建个Apache的服务器,把解压后的文件夹放到WWW文件夹下,运行本机服务器,就可以本地产看文档和运行案例了。

3 学习案例webgl_materials_car

  

    创建一个文件夹StudyThreejs,把解压后的three.js-r163放到里面,找到文件webgl_materials_car.html进行学习。

3.1 car.html部分

用VSCode 打开文件夹StudyThreejs,先创建文件car.html和car.js

打开car.html:

style模块把main.css里的#info复制粘贴过来,这一部分是界面的文字和按钮的布局

去掉界面滚动条

3.2 body部分

注意:

这里一开始弄错了,修改后OK了。

 3.3 car.html全部脚本

car.html如下,这一部分前度的知识我还是不太会哈



 
    
    threejs car 学习
    
	
    
 

    
        three.js car materials
Ferrari 458 Italia model by vicent091036


Body
Details
Glass

3.2 car.js部分

针对car.js:就是看着webgl_materials_car.html里的代码抄写一遍加深记忆,部分地方有自己的修改,比如记载改为了异步加载。

3.2.1 加载gltf模型

先在Init()里加载模型,可以看到是一个黑色的车

//引入Threejs
import * as THREE from 'three';
//引入gltf模型加载器GLTFLoader
import {GLTFLoader} from  "three/addons/loaders/GLTFLoader.js";
import {DRACOLoader} from  "three/addons/loaders/DRACOLoader.js";
//定义几个属性
let camera,scene,renderer;
function init(){
   //实例化场景
   scene=new THREE.Scene();
   scene.background=new THREE.Color(0xffffff);
  //实例化相机
  camera=new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.1, 100 );
  //相机位置
  camera.position.set(4.25,1.4,-4.5);
  camera.lookAt(0,0,0);
    
   //通过id获取html的canvas
   const container = document.getElementById('container');
   //实例化渲染器 
   renderer=new  THREE.WebGLRenderer({
       antialias:true, //是否执行抗锯齿。默认为false
   });
   renderer.setSize(window.innerWidth,window.innerHeight);//将输出canvas的大小调整为(width, height)并考虑设备像素比
   renderer.setPixelRatio( window.devicePixelRatio );//设置设备像素比。通常用于避免HiDPI设备上绘图模糊
  
   renderer.setAnimationLoop( render );  //请求再次执行函数animate 渲染下一帧    每个可用帧都会调用的函数render 
   renderer.toneMapping = THREE.ACESFilmicToneMapping;//色调映射   使用tonemapping可以塑造更真实的效果
   renderer.toneMappingExposure = 0.85;//色调映射的曝光级别。默认是1
   //把渲染的domElement添加到container上  要不画面看不到
   container.appendChild(renderer.domElement);
   
 //一个用于加载经过Draco压缩的图形库
 const dracLoader=new DRACOLoader();
 //参数是包含JS和WASM解压缩库的文件夹路径
 dracLoader.setDecoderPath('./three.js-r163/examples/jsm/libs/draco/gltf/');
 //gltf模型加载
 const gltfLoader=new GLTFLoader();
 //Draco是一个开源的库,主要用于压缩和解压缩三维模型及点云。 以客户端上解压缩为代价,显著减少压缩的图形。
 //独立的Draco文件后缀为.drc,其中包含顶点坐标,法线,颜色和其他的属性, Draco文件*不*包含材质,纹理,动画和节点结构-为了能使用这些特征,需要将Draco图形 嵌入到GLTF文件中。使用glTF-Pipeline可以将一个普通的GLTF文件转化为经过Draco压缩的GLTF文件。 当使用Draco压缩的GLTF模型时,GLTFLoader内部会调用DRACOLoader
 gltfLoader.setDRACOLoader(dracLoader);
 gltfLoader.load('./three.js-r163/examples/models/gltf/ferrari.glb',function(gltf){
     console.log(gltf.scene);
     const carModel=gltf.scene.children[0];
     scene.add(carModel);
 });
}
//进行渲染的方法  这个会每一帧都执行
function render(){
  
    renderer.render(scene,camera);
   
}
init();

鼠标右键选中car.html。点击OpenwithLiveServer运行,可以看到如下结果

打印的模型信息:

3.2.2 添加灯光

这时我们再init方法的后面添加一个灯的代码:

//直线光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 参数:光源颜色、光源强度
directionalLight.position.set(10, 10, 10); // 设置光源位置
scene.add(directionalLight); // 将光源添加到场景中
3.2.3 添加环境贴图

接下来添加环境贴图,同时隐藏掉灯光脚本:

接下来修改背景:

3.2.4 添加车身材质

运行结果如下:

效果是不是有了,接下来添加玻璃和细节材质,看后面的car.js的全部脚本。

3.2.5 添加地面网格
   //坐标格辅助对象. 坐标格实际上是2维线数组  参数: 坐标尺寸 坐标细分次数 中线颜色 坐标格网格线颜色
  const grid=new THREE.GridHelper(20,40,0xffffff,0xffffff);
   //opacity在0.0 - 1.0的范围内的浮点数,表明材质的透明度。值0.0表示完全透明,1.0表示完全不透明
   //如果材质的transparent属性未设置为true,则材质将保持完全不透明,此值仅影响其颜色。 默认值为1.0
   grid.material.opacity = 0.2;
   //depthWrite渲染此材质是否对深度缓冲区有任何影响。默认为true。
   //在绘制2D叠加时,将多个事物分层在一起而不创建z-index时,禁用深度写入会很有用
   grid.material.depthWrite = false;
   //定义此材质是否透明。这对渲染有影响,因为透明对象需要特殊处理,并在非透明对象之后渲染。
   //设置为true时,通过设置材质的opacity属性来控制材质透明的程度。默认值为false
   grid.material.transparent = true;
   scene.add( grid );
3.2.6 添加动画

这是需要在方法外添加参数const wheels=[];和   let grid ;  把init里grid前面的const去掉;

加载模型时需要保存轮胎到数组wheels里

3.2.6 添加控制器
3.2.7 添加雾效

没加雾效前:

添加雾效后:

3.2.8 添加车的影子
3.2.9 添加监听窗口大小变化的函数
3.2.10 添加性能监视器

3.2.11 car.js全部脚本

car.js代码加解释如下:

//引入Threejs
import * as THREE from 'three';
//引入gltf模型加载器GLTFLoader
import {GLTFLoader} from  "three/addons/loaders/GLTFLoader.js";
import {DRACOLoader} from  "three/addons/loaders/DRACOLoader.js";
//Three.js 中 RGBELoader 是一种用于加载高动态范围图像(High Dynamic Range,HDR)的 Loader,它可以将 .hdr 或 .rgbe 格式的 HDR 图像文件加载到 Three.js 的 WebGL 场景中,并方便地应用于场景渲染和光照等方面
import {RGBELoader} from  "three/addons/loaders/RGBELoader.js";
//引入轨道控制器   可以鼠标控制旋转 滚轮靠近和原理观察的目标物体
import {OrbitControls} from 'three/addons/controls/OrbitControls.js';
import Stats from 'three/addons/libs/stats.module.js';
//定义几个属性
let camera,scene,renderer;
let grid;
let controls;
let stats;
//车轮数组
const wheels=[];
function init(){
   //实例化场景
   scene=new THREE.Scene();
     scene.background=new THREE.Color(0x333333);
    //RGBELoader加载器异步加载hdr环境贴图
    new RGBELoader().loadAsync('./three.js-r163/examples/textures/equirectangular/venice_sunset_1k.hdr').then((texture)=>{
        scene.environment=texture;// 设置环境贴图
        scene.environment.mapping=THREE.EquirectangularRefractionMapping; // 设置映射类型
        //scene.background=texture;// 设置背景
    });
    scene.fog=new THREE.Fog(0x333333,10,15); //雾效
   
  //实例化相机
  camera=new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.1, 100 );
  //相机位置
  camera.position.set(4.25,1.4,-4.5);
  //camera.lookAt(0,0,0);
    
   //通过id获取html的canvas
   const container = document.getElementById('container');
    //性能监视器
 stats=new Stats();
 container.appendChild(stats.domElement);
   //实例化渲染器 
   renderer=new  THREE.WebGLRenderer({
       antialias:true, //是否执行抗锯齿。默认为false
   });
   renderer.setSize(window.innerWidth,window.innerHeight);//将输出canvas的大小调整为(width, height)并考虑设备像素比
   renderer.setPixelRatio( window.devicePixelRatio );//设置设备像素比。通常用于避免HiDPI设备上绘图模糊
  
   renderer.setAnimationLoop( render );  //请求再次执行函数animate 渲染下一帧    每个可用帧都会调用的函数render 
   renderer.toneMapping = THREE.ACESFilmicToneMapping;//色调映射   使用tonemapping可以塑造更真实的效果
   renderer.toneMappingExposure = 0.85;//色调映射的曝光级别。默认是1
   //把渲染的domElement添加到container上  要不画面看不到
   container.appendChild(renderer.domElement);
   
 //创建车身的材质
 const bodyMaterial=new THREE.MeshPhysicalMaterial({
    color:0xff0000,//材质的颜色
    metalness:1.0,//材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。0.0到1.0之间的值可用于生锈金属的外观。如果还提供了metalnessMap,则两个值相乘
    roughness:0.5,//材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。默认值为1.0。如果还提供roughnessMap,则两个值相乘。
    clearcoat:1.0,//表示clear coat层的强度,范围从0.0到1.0m,当需要在表面加一层薄薄的半透明材质的时候,可以使用与clear coat相关的属性,默认为0.0
    clearcoatRoughness:0.03 //clear coat层的粗糙度,由0.0到1.0。 默认为0.0
});
 //创建轮子的细节材质
 const detailsMaterial=new THREE.MeshPhysicalMaterial({
    color:0xffffff,
    metalness:1.0,
    roughness:0.5,      
});
//创建玻璃材质
const glassMaterial=new THREE.MeshPhysicalMaterial({
    color:0xffffff,
    metalness:0.25,
    roughness:0,
    transmission:1.0 //透光率(或者说透光性),范围从0.0到1.0。默认值是0.0。
});
    //界面上的几个按钮监听
    const bodyColorInput = document.getElementById( 'body-color' );
    bodyColorInput.addEventListener( 'input', function () {
        bodyMaterial.color.set( this.value );
    } );
    const detailsColorInput = document.getElementById( 'details-color' );
    detailsColorInput.addEventListener( 'input', function () {
        detailsMaterial.color.set( this.value );
    } );
    const glassColorInput = document.getElementById( 'glass-color' );
    glassColorInput.addEventListener( 'input', function () {
        glassMaterial.color.set( this.value );
    } );
 //车   
 //车阴影的图
 const shadow=new THREE.TextureLoader().load("./three.js-r163/examples/models/gltf/ferrari_ao.png");
 //一个用于加载经过Draco压缩的图形库
 const dracLoader=new DRACOLoader();
 //参数是包含JS和WASM解压缩库的文件夹路径
 dracLoader.setDecoderPath('./three.js-r163/examples/jsm/libs/draco/gltf/');
 //gltf模型加载
 const gltfLoader=new GLTFLoader();
 //Draco是一个开源的库,主要用于压缩和解压缩三维模型及点云。 以客户端上解压缩为代价,显著减少压缩的图形。
 //独立的Draco文件后缀为.drc,其中包含顶点坐标,法线,颜色和其他的属性, Draco文件*不*包含材质,纹理,动画和节点结构-为了能使用这些特征,需要将Draco图形 嵌入到GLTF文件中。使用glTF-Pipeline可以将一个普通的GLTF文件转化为经过Draco压缩的GLTF文件。 当使用Draco压缩的GLTF模型时,GLTFLoader内部会调用DRACOLoader
 gltfLoader.setDRACOLoader(dracLoader);
 gltfLoader.load('./three.js-r163/examples/models/gltf/ferrari.glb',function(gltf){
     console.log(gltf.scene);
     const carModel=gltf.scene.children[0];
      carModel.getObjectByName( 'body' ).material = bodyMaterial;//修改车 车身的材质
        carModel.getObjectByName( 'rim_fl' ).material = detailsMaterial;
        carModel.getObjectByName( 'rim_fr' ).material = detailsMaterial;
        carModel.getObjectByName( 'rim_rr' ).material = detailsMaterial;
        carModel.getObjectByName( 'rim_rl' ).material = detailsMaterial;
        carModel.getObjectByName( 'trim' ).material = detailsMaterial;
        carModel.getObjectByName( 'glass' ).material = glassMaterial;//修改玻璃材质
        //把四个车轮放到数组里
        wheels.push(
            carModel.getObjectByName( 'wheel_fl' ),
            carModel.getObjectByName( 'wheel_fr' ),
            carModel.getObjectByName( 'wheel_rl' ),
            carModel.getObjectByName( 'wheel_rr' )
        );
           // shadow 生成阴影
           const mesh = new THREE.Mesh(
            new THREE.PlaneGeometry( 0.655 * 4, 1.3 * 4 ),
            new THREE.MeshBasicMaterial( {
                map: shadow, //贴图
                //在使用此材质显示对象时要使用何种混合。必须将其设置为CustomBlending才能使用自定义blendSrc, blendDst 或者 [page:Constant blendEquation]
                blending: THREE.MultiplyBlending, 
                toneMapped: false, //定义这个材质是否会被渲染器的toneMapping设置所影响,默认为 true
                transparent: true //定义此材质是否透明。这对渲染有影响,因为透明对象需要特殊处理,并在非透明对象之后渲染。设置为true时,通过设置材质的opacity属性来控制材质透明的程度。 默认值为false。
            } )
        );
        mesh.rotation.x = - Math.PI / 2;
        mesh.renderOrder = 2;//渲染顺序
        carModel.add(mesh);
     scene.add(carModel);
 });
   //坐标格辅助对象. 坐标格实际上是2维线数组  参数: 坐标尺寸 坐标细分次数 中线颜色 坐标格网格线颜色
   grid=new THREE.GridHelper(20,40,0xffffff,0xffffff);
   //opacity在0.0 - 1.0的范围内的浮点数,表明材质的透明度。值0.0表示完全透明,1.0表示完全不透明
   //如果材质的transparent属性未设置为true,则材质将保持完全不透明,此值仅影响其颜色。 默认值为1.0
   grid.material.opacity = 0.2;
   //depthWrite渲染此材质是否对深度缓冲区有任何影响。默认为true。
   //在绘制2D叠加时,将多个事物分层在一起而不创建z-index时,禁用深度写入会很有用
   grid.material.depthWrite = false;
   //定义此材质是否透明。这对渲染有影响,因为透明对象需要特殊处理,并在非透明对象之后渲染。
   //设置为true时,通过设置材质的opacity属性来控制材质透明的程度。默认值为false
   grid.material.transparent = true;
   scene.add( grid );
   
    //实例化控制器 参数: camera控制的相机,renderer.domElement用于事件监听的HTML元素
    controls = new OrbitControls( camera, renderer.domElement);
    controls.target.set(0,0.5,0);//控制器的焦点设置
    controls.minDistance=2;//最近距离
    controls.maxDistance=9;//最远距离
    controls.maxPolarAngle = THREE.MathUtils.degToRad( 90 );//相机旋转时向下时限制到90度
    controls.update();//更新控制器
  //直线光源
// const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 参数:光源颜色、光源强度
// directionalLight.position.set(10, 10, 10); // 设置光源位置
// scene.add(directionalLight); // 将光源添加到场景中
 //监听窗口大小变化
 window.addEventListener('resize',onWindowResize);
}
//监听窗口大小变化的方法
function onWindowResize(){
    camera.aspect=window.innerWidth/window.innerHeight;//更新aspect     aspect摄像机视锥体的长宽比,通常是使用画布的宽/画布的高。默认值是1(正方形画布)
    camera.updateProjectionMatrix();//更新摄像机投影矩阵。在任何参数被改变以后必须被调用
    renderer.setSize(window.innerWidth,window.innerHeight);//更新渲染画布
}
//进行渲染的方法  这个会每一帧都执行
function render(){
    controls.update();//更新控制器。必须在摄像机的变换发生任何手动改变后调用, 或如果.autoRotate或.enableDamping被设置时,在update循环里调用
    const time=-performance.now()/1000;
    //四个轮胎转起来
    for(let i=0;i 

 4 最终效果

最终演示效果手机录屏如下:

three.js官方案例car演示

转载请注明来自码农世界,本文标题:《Three.js官方案例webgl》

百度分享代码,如果开启HTTPS请参考李洋个人博客
每一天,每一秒,你所做的决定都会改变你的人生!

发表评论

快捷回复:

评论列表 (暂无评论,75人围观)参与讨论

还没有评论,来说两句吧...

Top