Three.js官方案例webgl_materials_car学习

目录

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如下,这一部分前度的知识我还是不太会哈

<!DOCTYPE html>
<html lang="en">
 <head>
    <meta charset="utf-8">
    <title>threejs car 学习</title>
    <!-- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"> -->
	<!-- <link type="text/css" rel="stylesheet" href="./three.js-r163/examples/main.css"> -->
    <style>
        body{
            color: #bbbbbb;
            background: #333333;
            overflow: hidden;  /*不用滚动条*/
            margin: 0px ;
        }
        a {
				color: #08f;
		}
        .colorPicker{
            display: inline-block;
            margin: 0 10px
        }
        /* 
         按钮和文字的布局
        */
        #info {
	position: absolute;
	top: 0px;
	width: 100%;
	padding: 10px;
	box-sizing: border-box;
	text-align: center;
	-moz-user-select: none;
	-webkit-user-select: none;
	-ms-user-select: none;
	user-select: none;
	pointer-events: none;
	z-index: 1; /* TODO Solve this in HTML */
}

/* 添加这一行 几个颜色才能进行点击操作 */
input{
	pointer-events: auto;
}

</style>
 </head>

<body>
    <div id="info">
        <a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> car materials<br/>
			Ferrari 458 Italia model by <a href="https://sketchfab.com/models/57bf6cc56931426e87494f554df1dab6" target="_blank" rel="noopener">vicent091036</a>
			<br><br>
            <span class="colorPicker"><input id="body-color" type="color" value="#ff0000"></input><br/>Body</span>
			<span class="colorPicker"><input id="details-color" type="color" value="#ffffff"></input><br/>Details</span>
			<span class="colorPicker"><input id="glass-color" type="color" value="#ffffff"></input><br/>Glass</span>
    </div>

    <div id="container"></div>

    <!-- <div id="webgl" style="margin-top: 0px; margin-left: 0px;">  </div> -->
    <!--z这个使得js里 引入three.js方便 好像使得和正式开发时写法一致 -->
    <script type="importmap">
        {
            "imports": {
                "three": "./three.js-r163/build/three.module.js",  
                "three/addons/":"./three.js-r163/examples/jsm/"  
            }
        }
    </script>
    <!-- 引入car.js -->
    <script type="module"  src="car.js"> </script>


</body>
</html>

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<wheels.length;i++){
        wheels[i].rotation.x=time*Math.PI*2;
    }
    //这里是相对运动 地面动好像是车在动
    grid.position.z = - ( time ) % 1;
    //用相机(camera)渲染一个场景(scene)或是其它类型的object。
    // 渲染一般是在canvas上完成的,或者是renderTarget(通过.setRenderTarget指定)。
    // 默认情况下渲染缓存是会被清除的,但是你可以通过设置autoClear 属性的值为false来阻止渲染缓存被清除。 如果你想阻止某个指定的缓存被清空,可以设置autoClearColor、autoClearStencil或autoClearDepth属性的值为false来阻止其被清除。 如果想要强制清除一个或多个缓存,可以调用.clear。
    renderer.render(scene,camera);
    //性能监视器更新
    stats.update();
}

init();

 4 最终效果

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

three.js官方案例car演示

  • 30
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hemy1989

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值