Three.js之PBR材质与环境贴图

参考资料

知识点

注:基于Three.jsv0.155.0

  • PBR材质简介
  • PBR材质金属度和粗糙度:metalnessroughness
  • 环境贴图.envMap(金属效果):CubeTextureLoaderenvMapIntensity
  • MeshPhysicalMaterial清漆层:clearcoatclearcoatRoughness
  • 物理材质透光率.transmission、折射率.ior
  • 三维软件导出PBR材质属性

PBR材质简介

所谓PBR就是,基于物理的渲染(physically-based rendering)

  • 网格模型材质

    • MeshLambertMaterial: Lambert光照模型(漫反射)
    • MeshPhongMaterial:Phong光照模型(漫反射、高光反射)
    • MeshStandardMaterial和MeshPhysicalMaterial:基于物理的光照模型(微平面理论、能量守恒、菲涅尔反射...)

    PBR材质相比MeshLambertMaterial和MeshPhongMaterial可以提供更逼真的、更接近生活中的材质效果,当然也会占用更多的电脑硬件资源。

    通过MeshPhysicalMaterial文档,提供的资源,可以查看多个PBR材质的案例效果,系统课程中轿车展示案例也会用到PBR材质

  • 渲染占用资源和表现能力

    占用渲染资源 MeshBasicMaterial < MeshLambertMaterial < MeshPhongMaterial < MeshStandardMaterial < MeshPhysicalMaterial

    渲染表现能力 MeshBasicMaterial < MeshLambertMaterial < MeshPhongMaterial < MeshStandardMaterial < MeshPhysicalMaterial

代码实现

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Three.js</title>
</head>
  <body>
  </body>
  <!-- 具体路径配置,你根据自己文件目录设置,我的是课件中源码形式 -->
  <script type="importmap">
    {
      "imports": {
        "three": "./js/three.module.js",
        "three/addons/": "../three.js/examples/jsm/"
      }
    }
  </script>
  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';

    const width = window.innerWidth
    const height = window.innerHeight

    // 场景
    const scene = new THREE.Scene();

    const cubeTexture = new THREE.CubeTextureLoader()
      .setPath('./img/环境贴图3/')
      .load(['px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg'])

    const loader = new GLTFLoader();
    // 加载工厂文件
    loader.load('assets/金属.glb', function(gltf) {
      // 模型
      const model = gltf.scene;

      // 遍历模型
      model.traverse(function(child){
        // 判断是否为网格
        if(child.isMesh){
          // 设置材质
          child.material = new THREE.MeshStandardMaterial({
            metalness: 1.0,//金属度属性
            roughness: 0.5,//粗糙度属性
            envMap: cubeTexture,//环境贴图
            envMapIntensity: 0.5,//环境贴图强度
          })
        }
      });
      scene.add(model);
    })

    const loader2 = new GLTFLoader();
    // 加载工厂文件
    loader2.load('assets/轿车.glb', function(gltf) {
      // 模型
      const model = gltf.scene;
      model.position.set(100, 100, 100);
      console.log('🚀 ~ file: 7PBR材质与纹理贴图.html:61 ~ loader2.load ~ model:', model)

      var waike = model.getObjectByName('外壳01')
      
      waike.material = new THREE.MeshPhysicalMaterial({
        color: waike.material.color,
        clearcoat: 1.0, //物体表面清漆层或者说透明涂层的厚度
        clearcoatRoughness: 0.1, //物体表面清漆的粗糙度
        metalness: 0.5, //金属度属性
        roughness: 0.5, //粗糙度属性
        envMap: cubeTexture,//环境贴图
        envMapIntensity: 0.5,//环境贴图强度
      })

      var boli = model.getObjectByName('玻璃01')
      boli.material = new THREE.MeshPhysicalMaterial({
        color: boli.material.color,
        transmission: 1, //透射属性
        ior:1.5,//折射率
        metalness: 0.0, //金属度属性
        roughness: 0, //粗糙度属性
        envMap: cubeTexture,//环境贴图
        envMapIntensity: 0.5,//环境贴图强度
      })
      
      scene.add(model);
    })

    // 点光源
    const pointLight = new THREE.PointLight( 0xffffff, 1.0, 0, 0);
    pointLight.position.set(200, 200, 200 );
    scene.add( pointLight );
    
    // 环境光
    const ambientLight = new THREE.AmbientLight( 0xffffff, 1);
    scene.add( ambientLight );

    // 坐标系
    const axes = new THREE.AxesHelper(200);
    scene.add(axes);

    // 相机
    const camera = new THREE.PerspectiveCamera(75, width/height, 0.1, 3000);
    camera.position.set(348, 403, 362);
    camera.lookAt(0, 0, 0);

    // 渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(width, height);
    renderer.render(scene, camera);
    document.body.appendChild(renderer.domElement);

    renderer.outputColorSpace = THREE.SRGBColorSpace;//设置为SRGB颜色空间

    const controls = new OrbitControls(camera, renderer.domElement);

    // 渲染循环
    function render() {
        renderer.render(scene, camera);
        // console.log('🚀 ~ file: 7PBR材质与纹理贴图.html:110 ~ render ~ camera:', camera.position)
        requestAnimationFrame(render);
    }
    render();

    // 控制器

    controls.addEventListener('change', () => {
      // 因为动画渲染了,所以这里可以省略
      renderer.render(scene, camera);
    });
  </script>
</html>
相关推荐
gis分享者11 小时前
学习threejs,PerspectiveCamera透视相机和OrthographicCamera正交相机对比
threejs·透视相机·正交相机
gis分享者3 天前
学习threejs,scene.overrideMaterial全局材质效果
threejs·全局材质·overridemater
我码玄黄5 天前
在THREEJS中加载3dtile模型
前端·javascript·3d·threejs
gis分享者13 天前
学习threejs,加载天地图
threejs·加载天地图
踏实探索16 天前
Three.js教程_02场景、相机与渲染器全面解析
开发语言·javascript·数码相机·threejs
gis分享者17 天前
学习threejs,实现配合使用WebWorker
多线程·threejs·webworker
AllBlue17 天前
threejs相机辅助对象cameraHelper
threejs
gis分享者20 天前
学习threejs,使用VideoTexture实现视频Video更新纹理
threejs·视频贴图·videotexture
gis分享者21 天前
学习threejs,通过设置纹理属性来修改纹理贴图的位置和大小
threejs·纹理贴图·位置和大小
gis分享者25 天前
学习threejs,使用设置normalMap法向量贴图创建更加细致的凹凸和褶皱
threejs·normalmap·法向量贴图