【愚公系列】2023年08月 Three.js专题-纹理


前言

纹理是指由于物体内部或表面的微观结构、形态、组成、排列等因素所形成的外观或质感特征。它可以是线性的、非线性的、均匀的或不均匀的,可以在物体的表面或内部出现。纹理可以是自然界中的,也可以是人工制造的,是视觉艺术和设计中一个非常重要的元素。在数字图像处理中,纹理是图像分析和识别的一个重要因素。

一、纹理

1.简介

Three.js中的纹理贴图方式有以下几种:

  1. 基础纹理:使用纹理图像创建基本纹理,可以使用图片或视频等多种类型的纹理贴图。

  2. 环境贴图:创建环境贴图可以添加反射和折射效果,可以使用天空盒子或立方体纹理等。

  3. 光照贴图:使用光照贴图可以模拟光照效果,例如通过凹凸贴图、法线贴图、位移贴图等来模拟凹陷和凸起的效果。

  4. 烘培纹理:通过烘培过程将光影效果转换为纹理,可以提高性能和图形质量。

  5. 渲染目标纹理:使用渲染目标纹理可以将场景的渲染结果保存到纹理中,可以用于后处理、渲染效果等。

  6. 视频和动态纹理:可以使用视频或动态生成的图像作为纹理,动态纹理可以根据场景的变化实时更新。

2.属性

在Three.js中,贴图是指在材质表面上贴附一张图片纹理,通过纹理映射的方式来呈现出材质表面的不同效果和细节。下面是Three.js中常用的贴图属性:

扫描二维码关注公众号,回复: 16212998 查看本文章
  1. map:基础贴图,用于显示模型的颜色、灰度值和透明度。默认值是null。

  2. specularMap:高光贴图,用于显示材质的高光颜色和强度。默认值是null。

  3. bumpMap:凹凸贴图,用于显示模型表面的凸出和凹陷。默认值是null。

  4. normalMap:法线贴图,用于用来调整模型表面的法线,从而产生细节凹凸效果。默认值是null。

  5. displacementMap:位移贴图,用于改变模型表面的位置,从而创建模型的几何细节。默认值是null。

  6. alphaMap:透明贴图,用于设置材质透明度。默认值是null。

  7. emissiveMap:自发光贴图,用于显示模型的自发光效果。默认值是null。

  8. envMap:环境贴图,用于模拟材质被周围环境反射的效果。默认值是null。

3.案例

3.1 基础纹理

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      
      
      margin: 0;
      padding: 0;
    }
  </style>
  <script src="../lib/three/three.js"></script>
</head>
<body>

</body>
</html>

<script>
  // 创建一个场景
  const scene = new THREE.Scene();

  // 创建一个相机 视点
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
  // 设置相机的位置
  camera.position.set(0,0,20);

  // 创建一个渲染器
  const renderer = new THREE.WebGLRenderer();
  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  // 添加一个立方体
  // 定义了一个立方体的对象
  const geometry = new THREE.PlaneBufferGeometry(10, 10, 2, 2);

  // 创建一个纹理加载器
  const loader = new THREE.TextureLoader()
  loader.load('../assets/grass.png', (texture) => {
      
      

    // 创建材质
    const lambert = new THREE.MeshLambertMaterial({
      
      
      map: texture
    })

    const mesh = new THREE.Mesh(geometry, lambert);

    // 添加到场景里
    scene.add(mesh);
  });

  // 添加灯光
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-10,10,90);
  scene.add(spotLight);

  const animation = () => {
      
      
    // 渲染
    renderer.render(scene, camera);

    requestAnimationFrame(animation);
  }
  animation()
</script>

在这里插入图片描述

3.2 canvas贴图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      
      
      margin: 0;
      padding: 0;
    }
  </style>
  <script src="../lib/three/three.js"></script>

  <!-- 轨道控件 -->
  <script src="../lib/three/OrbitControls.js"></script>
</head>
<body>

</body>
</html>

<script>
  const clock = new THREE.Clock()
  // 创建一个场景
  const scene = new THREE.Scene();

  // 创建一个相机 视点
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
  // 设置相机的位置
  camera.position.set(100,100,0);
  camera.lookAt(new THREE.Vector3(0,0,0));

  const controls = new THREE.OrbitControls(camera)
  controls.minDistance = 1;
  controls.maxDistance = 50;

  // 创建一个渲染器
  const renderer = new THREE.WebGLRenderer();
  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  renderer.setClearColor(0xffffff);
  // 添加灯光
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(2000,8000,4000);
  scene.add(spotLight);

  function getSprite() {
      
      
    const canvas = document.createElement('canvas')
    canvas.width = 160;
    canvas.height = 160;

    const c = canvas.getContext('2d')

    c.fillStyle = 'red';
    c.arc(80, 80, 32, 0, Math.PI * 2);
    c.fill();

    const texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;
    return texture;
  }

  // 创建一个球体 和一个立方体
  const cubeGeometry = new THREE.BoxGeometry(5,5,5);

  // 立方体贴图是和环境一致, 球体是跟随当前环境
  const cubeMaterial = new THREE.MeshBasicMaterial({
      
       map: getSprite() })

  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

  scene.add(cube)

  const animation = () => {
      
      
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    controls.update(clock.getDelta());
    // 渲染
    renderer.render(scene, camera);

    requestAnimationFrame(animation);
  }
  animation()
</script>

在这里插入图片描述

3.3 凹凸贴图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      
      
      margin: 0;
      padding: 0;
    }
  </style>
  <script src="../lib/three/three.js"></script>
</head>
<body>

</body>
</html>

<script>
  // 创建一个场景
  const scene = new THREE.Scene();

  // 创建一个相机 视点
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
  // 设置相机的位置
  camera.position.set(0,0,20);

  // 创建一个渲染器
  const renderer = new THREE.WebGLRenderer();
  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  // 添加一个立方体
  // 定义了一个立方体的对象
  const geometry = new THREE.BoxGeometry(6, 6, 3);

  // 创建一个纹理加载器
  const loader = new THREE.TextureLoader()
  loader.load('../assets/wall.jpg', (texture) => {
      
      
    // 创建材质
    const lambert = new THREE.MeshPhongMaterial({
      
      
      map: texture
    })

    const mesh = new THREE.Mesh(geometry, lambert);
    mesh.rotation.y = -0.1;
    mesh.position.x = -4;

    // 添加到场景里
    scene.add(mesh);
  });
  renderer.setClearColor(0xffffff)
  loader.load('../assets/wall.jpg', (texture) => {
      
      
    loader.load('../assets/wall-bump.jpg', (bump) => {
      
      
      // 创建材质
      const lambert = new THREE.MeshPhongMaterial({
      
      
        map: texture,
        bumpMap: bump,
        bumpScale: 0.2,
      })

      const mesh = new THREE.Mesh(geometry, lambert);
      mesh.rotation.y = -0.5;
      mesh.position.x = 4;

      // 添加到场景里
      scene.add(mesh);
    });
  });

  // 添加灯光
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-10,10,90);
  scene.add(spotLight);

  const animation = () => {
      
      
    // 渲染
    renderer.render(scene, camera);

    requestAnimationFrame(animation);
  }
  animation()
</script>

在这里插入图片描述

3.4 法向贴图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      
      
      margin: 0;
      padding: 0;
    }
  </style>
  <script src="../lib/three/three.js"></script>
</head>
<body>

</body>
</html>

<script>
  // 创建一个场景
  const scene = new THREE.Scene();

  // 创建一个相机 视点
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
  // 设置相机的位置
  camera.position.set(0,0,40);

  // 创建一个渲染器
  const renderer = new THREE.WebGLRenderer();
  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  // 添加一个立方体
  // 定义了一个立方体的对象
  const geometry = new THREE.BoxGeometry(10, 10, 10);

  // 创建一个纹理加载器
  const loader = new THREE.TextureLoader()

  // 创建材质
  const lambert = new THREE.MeshPhongMaterial({
      
      
    map: THREE.ImageUtils.loadTexture('../assets/plaster.jpg'),
  })

  const mesh = new THREE.Mesh(geometry, lambert);
  mesh.rotation.y = 0.5;
  mesh.position.x = -12;

  // 添加到场景里
  scene.add(mesh);


  renderer.setClearColor(0xffffff)

  // 创建材质
  const lambert1 = new THREE.MeshPhongMaterial({
      
      
    map: THREE.ImageUtils.loadTexture('../assets/plaster.jpg'),
    normalMap: THREE.ImageUtils.loadTexture('../assets/plaster-normal.jpg'),
  })

  const mesh2 = new THREE.Mesh(geometry, lambert1);
  mesh2.rotation.y = -0.5;
  mesh2.position.x = 12;

  // 添加到场景里
  scene.add(mesh2);

  // 添加灯光
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(-10,10,90);
  scene.add(spotLight);

  const animation = () => {
      
      
    // 渲染
    renderer.render(scene, camera);

    requestAnimationFrame(animation);
  }
  animation()
</script>

在这里插入图片描述

3.5 环境贴图

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      
      
      margin: 0;
      padding: 0;
    }
  </style>
  <script src="../lib/three/three.js"></script>

  <!-- 轨道控件 -->
  <script src="../lib/three/OrbitControls.js"></script>
</head>
<body>

</body>
</html>

<script>
  const clock = new THREE.Clock()
  // 创建一个场景
  const scene = new THREE.Scene();

  // 创建一个相机 视点
  const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
  // 设置相机的位置
  camera.position.set(100,100,0);
  camera.lookAt(new THREE.Vector3(0,0,0));

  const controls = new THREE.OrbitControls(camera)
  controls.minDistance = 1;
  controls.maxDistance = 50;

  // 创建一个渲染器
  const renderer = new THREE.WebGLRenderer();
  // 设置渲染器尺寸
  renderer.setSize(window.innerWidth, window.innerHeight);

  document.body.appendChild(renderer.domElement);

  // 添加灯光
  const spotLight = new THREE.SpotLight(0xffffff);
  spotLight.position.set(2000,8000,4000);
  scene.add(spotLight);

  // 创建虚拟的场景
  const imgs = [
    '../assets/sky/right.jpg',
    '../assets/sky/left.jpg',
    '../assets/sky/top.jpg',
    '../assets/sky/bottom.jpg',
    '../assets/sky/front.jpg',
    '../assets/sky/back.jpg',
  ]

  const mats = [];
  for (let i = 0; i < imgs.length; i++) {
      
      
    mats.push(new THREE.MeshBasicMaterial({
      
      
      map: THREE.ImageUtils.loadTexture(imgs[i]),
      side: THREE.DoubleSide,
    }))
  }

  const skybox = new THREE.Mesh(new THREE.BoxGeometry(100, 100, 100), new THREE.MeshFaceMaterial(mats))

  scene.add(skybox)

  // 创建一个球体 和一个立方体
  const sphereGeometry = new THREE.SphereGeometry(4, 15, 15);
  const cubeGeometry = new THREE.BoxGeometry(5,5,5);

  // 立方体贴图是和环境一致, 球体是跟随当前环境
  const cubeMaterial = new THREE.MeshBasicMaterial({
      
      
    envMap: THREE.ImageUtils.loadTextureCube(imgs)
  })

  // 通过立方体相机来实现
  const cubeCamera = new THREE.CubeCamera(0.1, 2000, 256);
  scene.add(cubeCamera);

  const sphereMaterial = new THREE.MeshBasicMaterial({
      
      
    envMap: cubeCamera.renderTarget,
  })

  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);

  sphere.position.x = 5;
  cube.position.x = -5;
  scene.add(sphere)
  scene.add(cube)

  const animation = () => {
      
      
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;
    controls.update(clock.getDelta());
    // 渲染
    renderer.render(scene, camera);

    requestAnimationFrame(animation);

    cubeCamera.updateCubeMap(renderer, scene);
  }
  animation()
</script>

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/aa2528877987/article/details/132250116