three.js – Environment Map

  • Environment Map
    • as a background
    • as reflection
    • as lighting
  • Set up

<script setup>
  import * as THREE from  three 
  import {OrbitControls} from  three/addons/controls/OrbitControls.js 
  import GUI from  lil-gui 

  /**
   * scene
  */
  const scene = new THREE.Scene()

  /**
   * torus knot
  */
  const torusKnot = new THREE.Mesh(
    new THREE.TorusKnotGeometry(1, 0.4, 100, 16),
    new THREE.MeshBasicMaterial()
  )
  torusKnot.position.y = 4
  scene.add(torusKnot)

  /**
   * camera
  */
  const camera = new THREE.PerspectiveCamera(
    75, 
    window.innerWidth / window.innerHeight, 
    0.1, 
    100)
  camera.position.set(4, 5, 4)
  scene.add(camera)

  /**
   * renderer
  */
  const renderer = new THREE.WebGLRenderer({})
  renderer.setSize(window.innerWidth, window.innerHeight)
  renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
  document.body.appendChild(renderer.domElement)

  window.addEventListener( resize , () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()

    renderer.setSize(window.innerWidth, window.innerHeight) 
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))  
  })

  /**
   * control
  */
  const controls = new OrbitControls(camera, renderer.domElement)
  controls.target.y = 3.5
  controls.enableDamping = true

  /**
   * tick
  */
  const tick = () => {
    controls.update()
    renderer.render(scene, camera)
    requestAnimationFrame(tick)
  }
  tick()

  /**
   * gui
  */
  const gui = new GUI()
</script>

three.js - Environment Map

  • Model
    • 添加model后向下移动camera就能看见了

    import { GLTFLoader } from  three/addons/loaders/GLTFLoader.js ;
    
    /**
     * loaders
    */
    const gltfLoader = new GLTFLoader()
    ...
    ...
    /**
     * models
    */
    gltfLoader.load(
       ../public/models/environment-map/models/FlightHelmet/glTF/FlightHelmet.gltf ,
      (gltf) => {
        // console.log((gltf));
        scene.add(gltf.scene)
      }
    )
    

    three.js - Environment Map

    • the model is too small and it s black, because its materials are MeshStandardMaterial and those need light
    • cube texture environment map, load the textures in this order: positive x, negative x, positive y, negative y, positive z, negative z

    /**
     * loaders
    */
    ...
    const cubeTextureLoader = new THREE.CubeTextureLoader()
    
    /**
     * environment map
    */
    // LDR cube texture
    const environmentMap = cubeTextureLoader.load([
       ../public/models/environment-map/environmentMaps/0/px.png ,
       ../public/models/environment-map/environmentMaps/0/nx.png ,
       ../public/models/environment-map/environmentMaps/0/py.png ,
       ../public/models/environment-map/environmentMaps/0/ny.png ,
       ../public/models/environment-map/environmentMaps/0/pz.png ,
       ../public/models/environment-map/environmentMaps/0/nz.png 
    ])
    
    scene.background = environmentMap
    

    • move the torus knot to the side and change its material to MeshStandardMaterial

    /**
     * torus knot
    */
    const torusKnot = new THREE.Mesh(
      new THREE.TorusKnotGeometry(1, 0.4, 100, 16),
      new THREE.MeshStandardMaterial({
        roughness: 0.3,
        metalness: 1,
        color: 0xaaaaaa
      })  )
    torusKnot.position.x = -4
    ...
    

    three.js - Environment Map

    • use the environment map to light up the model, 也可以在单个model的material上设置envMap属性,但我们import的model层级结构比较复杂,不方便遍历添加,所以我们使用以下方法

    /**
     * environment map
    */
    // LDR cube texture
    ...
    
    scene.environment = environmentMap // to the hold scene
    scene.background = environmentMap
    

    three.js - Environment Map

    • control the environment map s intensity, it has to be done on each material, we re going to touch the hole scene using traverse(), this method is available on object3D, we ll do it in a separated function and call it once is loaded
    • we only want to apply the environment map to the Meshes that have a MeshStandardMaterial

    /**
     * update all materials
    */
    const updateAllMaterials = () => {
      scene.traverse(child => {
        // console.log(child) // mesh, group, perspectiveCamera...
    
        // child instanceof THREE.Mesh && child.material instanceof THREE.MeshStandardMaterial
        if(child.isMesh && child.material.isMeshStandardMaterial) {
          // console.log(child);
          child.material.envMapIntensity = 3  // 增强环境贴图的反射强度
        }
      })
    }
    

    /**
     * models
    */
    gltfLoader.load(
       ../public/models/environment-map/models/FlightHelmet/glTF/FlightHelmet.gltf ,
      (gltf) => {
        ...
        updateAllMaterials()
      }
    )
    

    three.js - Environment Map

    • control the envMapIntensity by using the Dat.gui

    /**
     * gui
    */
    const gui = new GUI()
    const global = {
      envMapIntensity: 1
    }
    gui
      .add(global,  envMapIntensity )
      .min(0)
      .max(10)
      .step(0.001)
      .onChange(updateAllMaterials)
    

    /**
     * update all materials
    */
    const updateAllMaterials = () => {
      scene.traverse(child => {
          ...
          child.material.envMapIntensity = global.envMapIntensity // 调整环境贴图的反射强度
        }
      })
    }
    

  • Background blurriness and intensity 模糊度、强度

  scene.backgroundBlurriness = 0
  scene.backgroundIntensity = 1

  gui
    .add(scene,  backgroundBlurriness )
    .min(0)
    .max(1)
    .step(0.001)
  gui
    .add(scene,  backgroundIntensity )
    .min(0)
    .max(10)
    .step(0.001)

  • HDRI – Equirectangular Environment Map 等距矩形环境贴图
    • HDR Files: File extension is .hdr, high dynamic range 高动态范围
    • HDRI: color values stored have a much higher range than a traditional image
    • Equirectangular: only one picture containing kind of a 360° view of the surrounding
    • comment the environment map(keep the backgroundBlurriness and backgroundIntensity)

    /**
     * environment map
    */
    // LDR cube texture
    // const environmentMap = cubeTextureLoader.load([
    //    ../public/models/environment-map/environmentMaps/0/px.png ,
    //    ../public/models/environment-map/environmentMaps/0/nx.png ,
    //    ../public/models/environment-map/environmentMaps/0/py.png ,
    //    ../public/models/environment-map/environmentMaps/0/ny.png ,
    //    ../public/models/environment-map/environmentMaps/0/pz.png ,
    //    ../public/models/environment-map/environmentMaps/0/nz.png 
    // ])
    
    // scene.environment = environmentMap // to the hold scene
    // scene.background = environmentMap
    
    scene.backgroundBlurriness = 0
    scene.backgroundIntensity = 1
    

    • load and use the HDRI, we need to use the RGBELoader, RGBE stands for Red Blue Green Exponent, the exponent means stores the brightness, 使用 RGBELoader 加载的背景看起来要更亮,由于存储在文件中的值更多、范围更大

    import {RGBELoader} from  three/addons/loaders/RGBELoader.js 
    
    /**
     * loaders
    */
    ...
    const rgbeLoader = new RGBELoader()
    

    /**
     * environment map
    */
    ...
    ...
    // HDR (RGBE) equirectangular
    rgbeLoader.load( ../public/models/environment-map/environmentMaps/0/2k.hdr , (environmentMap) => {
      environmentMap.mapping = THREE.EquirectangularReflectionMapping
    
      scene.environment = environmentMap
      scene.background = environmentMap
    })
    
    scene.backgroundBlurriness = 0
    scene.backgroundIntensity = 1
    

    three.js - Environment Map

    • 这里我们展示一些通过blender创建的不同类型的HDR背景图所呈现的效果

      three.js - Environment Map

      three.js - Environment Map

  • AI generated environment using NVIDIA Canvas
    • the software is in beta and only works on windows
    • the extension is .exr, our exported file is also an HDR, but EXR can also store layer
    • import the EXRLoader

  ...
  import { EXRLoader } from  three/addons/loaders/EXRLoader.js ;

  /**
   * loaders
  */
  ...
  const exrLoader = new EXRLoader()

  // HDR (RGBE) equirectangular
  // rgbeLoader.load( ../public/environment-map/environmentMaps/blender-2k-1.hdr , environmentMap => {
  //   environmentMap.mapping = THREE.EquirectangularReflectionMapping

  //   scene.environment = environmentMap
  //   scene.background = environmentMap
  // })

  // HDR (EXR) equirectangular
  exrLoader.load( ../public/environment-map/environmentMaps/nvidia-canvas-4k.exr , environmentMap => {
    environmentMap.mapping = THREE.EquirectangularReflectionMapping

    scene.environment = environmentMap
    scene.background = environmentMap
  })

three.js - Environment Map

  • AI generated environment map using BlockadeLabs

  /**
   * loaders
  */
  ...
  const textureLoader = new THREE.TextureLoader()

  // HDR (RGBE) equirectangular
  // rgbeLoader.load( ../public/environment-map/environmentMaps/blender-2k-1.hdr , environmentMap => {
  //   environmentMap.mapping = THREE.EquirectangularReflectionMapping

  //   scene.environment = environmentMap
  //   scene.background = environmentMap
  // })

  // HDR (EXR) equirectangular
  // exrLoader.load( ../public/environment-map/environmentMaps/nvidia-canvas-4k.exr , environmentMap => {
  //   environmentMap.mapping = THREE.EquirectangularReflectionMapping

  //   scene.environment = environmentMap
  //   scene.background = environmentMap
  // })
  
  // scene.backgroundBlurriness = 0
  // scene.backgroundIntensity = 1

  // LDR equirectangular
  const environmentMap = textureLoader.load( ../public/environment-map/environmentMaps/blockadesLabsSkybox/anime_art_style_japan_streets_with_cherry_blossom_.jpg )
  environmentMap.mapping = THREE.EquirectangularReflectionMapping
  environmentMap.colorSpace = THREE.SRGBColorSpace
  scene.environment = environmentMap
  scene.background = environmentMap

three.js - Environment Map

  • Ground Projected Environment Map
    • when using the environment map as background, the objects look like are flying
    • to use on of the HDR environment maps, only as the environment
  • RealTime EnvironmentMap

    /**
     * real time environment map
    */
    const environmentMap = textureLoader.load( ../public/environment-map/environmentMaps/blockadesLabsSkybox/interior_views_cozy_wood_cabin_with_cauldron_and_p.jpg )
    environmentMap.mapping = THREE.EquirectangularReflectionMapping
    environmentMap.colorSpace = THREE.SRGBColorSpace
    
    scene.background = environmentMap
    

    • we re going to create a torus or a donut surrounding the scene and try to make the donut illuminate and reflect on the surface of our objects

    /**
     * holy donut
    */
    const holyDonut = new THREE.Mesh(
      new THREE.TorusGeometry(8, 0.5),
      new THREE.MeshBasicMaterial({color:  white })
    )
    holyDonut.position.y = 3.5
    scene.add(holyDonut)
    

    • we re going to render the scene inside our own environment map texture and it s going to be a cube texture
    • 创建立方体纹理:we need to use WebGLCubeRenderTarget, we need to create textures on each frame

    /**
     * cube render target
    */
    const cubeRenderTarget = new THREE.WebGLCubeRenderTarget(
      256,  // 分辨率
      {
        type: THREE.HalfFloatType
      }
    )
    scene.environment = cubeRenderTarget.texture
    

    • we need to use CubeCamera, because we need to render 6 texture for each face

    // cube camera
    const cubeCamera = new THREE.CubeCamera(0.1, 100, cubeRenderTarget) // near, far
    

    /**
     * tick
    */
    const clock = new THREE.Clock()
    const tick = () => {
      const elapsedTime = clock.getElapsedTime()
    
      if(holyDonut) {
        holyDonut.rotation.x = Math.sin(elapsedTime) * 2
        cubeCamera.update(renderer, scene)
      }
    
      controls.update()
      renderer.render(scene, camera)
      requestAnimationFrame(tick)
    }
    tick()
    

    three.js - Environment Map

    • we can make the cube color go beyond the 0 to 1 range

    /**
     * holy donut
    */
    const holyDonut = new THREE.Mesh(
      ...
      new THREE.MeshBasicMaterial({color: new THREE.Color(10, 4, 2)})
    )
    ...
    

    three.js - Environment Map

© 版权声明

相关文章

暂无评论

none
暂无评论...