[Yugong Series] August 2023 Three.js Topic - Texture


foreword

Texture refers to the appearance or texture characteristics formed by the microstructure, shape, composition, arrangement and other factors inside or on the surface of an object. It can be linear, nonlinear, uniform or inhomogeneous, and can occur on the surface or inside an object. Texture, which can be found in nature or man-made, is a very important element in visual art and design. In digital image processing, texture is an important factor in image analysis and recognition.

1. Texture

1 Introduction

The texture mapping methods in Three.js are as follows:

  1. Basic Texture: Use texture images to create basic textures, and you can use various types of texture maps such as pictures or videos.

  2. Environment Maps: Create environment maps to add reflection and refraction effects, use skyboxes or cube textures, etc.

  3. Lightmap: Lightmaps can be used to simulate lighting effects, such as concave and convex effects through bump maps, normal maps, displacement maps, etc.

  4. Baking Textures: The baking process converts light and shadow effects into textures, which can improve performance and graphics quality.

  5. Render target texture: Use the render target texture to save the rendering result of the scene to the texture, which can be used for post-processing, rendering effects, etc.

  6. Video and dynamic textures: Video or dynamically generated images can be used as textures, and dynamic textures can be updated in real time according to changes in the scene.

2. Properties

In Three.js, texture refers to attaching a picture texture on the material surface, and presenting different effects and details of the material surface through texture mapping. The following are commonly used texture properties in Three.js:

  1. map: Basic texture, used to display the color, grayscale value and transparency of the model. The default value is null.

  2. specularMap: Specular map, used to display the specular color and intensity of the material. The default value is null.

  3. bumpMap: Bump map, used to display the protrusion and depression of the model surface. The default value is null.

  4. normalMap: A normal map, used to adjust the normal of the model surface to produce a detailed bump effect. The default value is null.

  5. displacementMap: Displacement map used to change the position of the surface of the model to create the geometric details of the model. The default value is null.

  6. alphaMap: Transparent map, used to set material transparency. The default value is null.

  7. emissiveMap: Emissive map, used to display the self-illumination effect of the model. The default value is null.

  8. envMap: Environment map, used to simulate the effect of the material being reflected by the surrounding environment. The default value is null.

3. Case

3.1 Basic texture

<!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>

insert image description here

3.2 canvas texture

<!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>

insert image description here

3.3 Bump Mapping

<!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>

insert image description here

3.4 Normal map

<!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>

insert image description here

3.5 Environment Map

<!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>

insert image description here

Guess you like

Origin blog.csdn.net/aa2528877987/article/details/132250116