[Yugong シリーズ] 2023 年 8 月 Three.js トピック - テクスチャ


序文

質感とは、物体の内部または表面上の微細構造、形状、組成、配置およびその他の要因によって形成される外観または質感の特徴を指します。それは線形、非線形、均一または不均一であり、物体の表面または内部で発生する可能性があります。自然界または人工的に見られるテクスチャは、ビジュアル アートやデザインにおいて非常に重要な要素です。デジタル画像処理では、テクスチャは画像の分析と認識における重要な要素です。

1. テクスチャー

1 はじめに

Three.js のテクスチャ マッピングのメソッドは次のとおりです。

  1. 基本テクスチャ: テクスチャ イメージを使用して基本テクスチャを作成し、写真やビデオなどのさまざまなタイプのテクスチャ マップを使用できます。

  2. 環境マップ: 環境マップを作成して、反射および屈折効果を追加したり、スカイボックスやキューブ テクスチャなどを使用したりできます。

  3. ライトマップ: ライトマップは、バンプ マップ、法線マップ、ディスプレイスメント マップなどによる凹凸効果などの照明効果をシミュレートするために使用できます。

  4. テクスチャのベイク処理: ベイク処理により、光と影の効果がテクスチャに変換され、パフォーマンスとグラフィックスの品質が向上します。

  5. レンダー ターゲット テクスチャ: レンダー ターゲット テクスチャを使用して、シーンのレンダリング結果をテクスチャに保存します。これは、後処理やレンダリング エフェクトなどに使用できます。

  6. ビデオとダイナミック テクスチャ: ビデオまたは動的に生成された画像をテクスチャとして使用でき、ダイナミック テクスチャはシーンの変化に応じてリアルタイムで更新できます。

2. プロパティ

Three.js では、テクスチャとは、マテリアルの表面に絵のテクスチャを貼り付け、テクスチャ マッピングを通じてマテリアルの表面のさまざまな効果や詳細を表現することを指します。以下は、Three.js で一般的に使用されるテクスチャ プロパティです。

  1. マップ: モデルの色、グレースケール値、透明度を表示するために使用される基本的なテクスチャ。デフォルト値は null です。

  2. specularMap: マテリアルの鏡面カラーと強度を表示するために使用される鏡面マップ。デフォルト値は null です。

  3. バンプマップ: モデル表面の凹凸を表示するために使用されるバンプ マップ。デフォルト値は 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 キャンバスのテクスチャ

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