three.js基础之材质Material

init.js增加共用方法

function addMaterialSettings(gui, controls, material, folderName = "Material") {
  controls.material = material;

  const folder = gui.addFolder(folderName);
  folder.add(controls.material, "id");
  folder.add(controls.material, "uuid");
  folder.add(controls.material, "name");
  folder.add(controls.material, "opacity", 0, 1, 0.01);
  folder.add(controls.material, "transparent");
  folder.add(controls.material, "visible");
  folder.add(controls.material, "side", { FrontSide: 0, BackSide: 1, BothSides: 2 }).onChange(function (side) {
    controls.material.side = parseInt(side);
  });
  folder.add(controls.material, "colorWrite");
  folder.add(controls.material, "premultipliedAlpha");
  folder.add(controls.material, "dithering");
  folder.add(controls.material, "shadowSide", { FrontSide: 0, BackSide: 1, BothSides: 2 });
  folder.add(controls.material, "vertexColors", { yes: true, no: false }).onChange(function (vertexColors) {
    material.vertexColors = parseInt(vertexColors);
  });

  return folder;
}

function addSpecificMaterialSettings(gui, controls, material, name) {
  controls.material = material;

  var folderName = name !== undefined ? name : "THREE." + material.type;
  var folder = gui.addFolder(folderName);
  switch (material.type) {
    case "MeshNormalMaterial":
      folder.add(controls.material, "wireframe");
      return folder;

    case "MeshPhongMaterial":
      controls.specular = material.specular.getStyle();
      folder.addColor(controls, "specular").onChange(function (e) {
        material.specular.setStyle(e);
      });
      folder.add(material, "shininess", 0, 100, 0.01);
      return folder;

    case "MeshStandardMaterial":
      controls.color = material.color.getStyle();
      folder.addColor(controls, "color").onChange(function (e) {
        material.color.setStyle(e);
      });
      controls.emissive = material.emissive.getStyle();
      folder.addColor(controls, "emissive").onChange(function (e) {
        material.emissive.setStyle(e);
      });
      folder.add(material, "metalness", 0, 1, 0.01);
      folder.add(material, "roughness", 0, 1, 0.01);
      folder.add(material, "wireframe");

      return folder;
  }
}

MeshBasicMaterial

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  // 基础网格材质,一个以简单着色(平面或线框)方式来绘制几何体的材质。这种材质不受光照的影响。
  // color : Color 材质的颜色(Color),默认值为白色 (0xffffff)。
  // alphaMap : Texture alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。
  // envMap : Texture 环境贴图。默认值为null。
  // map : Texture 颜色贴图。
  // fog : Boolean 材质是否受雾影响。默认为true。
  // wireframe : Boolean 将几何体渲染为线框。默认值为false
  // wireframeLinecap : String 定义线两端的外观。可选值为 'butt','round' 和 'square'。默认为'round'。
  // wireframeLinejoin : String 定义线连接节点的样式。可选值为 'round', 'bevel' 和 'miter'。默认值为 'round'。
  // wireframeLinewidth : Float 控制线框宽度。默认值为1。
  // 继承Material的属性:
  // id : Integer 此材质实例的唯一编号。
  // uuid : String 此材质实例的UUID,会自动分配,不应该被更改。
  // name : String 对象的可选名称(不必是唯一的)。默认值为空字符串
  // opacity : Float 在0.0 - 1.0的范围内的浮点数,表明材质的透明度。值0.0表示完全透明,1.0表示完全不透明。默认值为1.0。
  // shadowSide : Integer 定义投影的面。设置时,可以是THREE.FrontSide, THREE.BackSide, THREE.DoubleSide。默认值为 null。
  // side : Integer 定义将要渲染哪一面 - 正面,背面或两者。 默认为THREE.FrontSide。
  // transparent : Boolean 定义此材质是否透明。设置为true时,通过设置材质的opacity属性来控制材质透明的程度。默认值为false。
  // vertexColors : Boolean 是否使用顶点着色。默认值为false。
  // visible : Boolean 此材质是否可见。默认为true。
  const meshMaterial = new THREE.MeshBasicMaterial({
    color: 0x7777ff,
    name: "Basic Material",
  });
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: meshMaterial.color.getStyle(),
      selectedMesh: "cube",
    };

    addMaterialSettings(gui, controls, meshMaterial);

    const spGui = gui.addFolder("MeshBasicMaterial");
    spGui.addColor(controls, "color").onChange(function (e) {
      meshMaterial.color.setStyle(e);
    });
    spGui.add(meshMaterial, "wireframe");
    spGui.add(meshMaterial, "wireframeLinewidth", 0, 20);
    spGui.add(meshMaterial, "wireframeLinejoin", ["round", "bevel", "miter"]).onChange(function (e) {
      meshMaterial.wireframeLinejoin = e;
    });
    spGui.add(meshMaterial, "wireframeLinecap", ["butt", "round", "square"]).onChange(function (e) {
      meshMaterial.wireframeLinecap = e;
    });

    return controls;
  }
</script>

多个材质

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  const group = new THREE.Mesh();
  const mats = [];
  mats.push(
    new THREE.MeshBasicMaterial({
      color: 0x009e60,
    })
  );
  mats.push(
    new THREE.MeshBasicMaterial({
      color: 0x0051ba,
    })
  );
  mats.push(
    new THREE.MeshBasicMaterial({
      color: 0xffd500,
    })
  );
  mats.push(
    new THREE.MeshBasicMaterial({
      color: 0xff5800,
    })
  );
  mats.push(
    new THREE.MeshBasicMaterial({
      color: 0xc41e3a,
    })
  );
  mats.push(
    new THREE.MeshBasicMaterial({
      color: 0xffffff,
    })
  );

  for (let x = 0; x < 3; x++) {
    for (let y = 0; y < 3; y++) {
      for (let z = 0; z < 3; z++) {
        const cubeGeom = new THREE.BoxGeometry(2.9, 2.9, 2.9);
        const cube = new THREE.Mesh(cubeGeom, mats);
        cube.position.set(x * 3 - 3, y * 3 - 3, z * 3 - 3);

        group.add(cube);
      }
    }
  }

  group.scale.copy(new THREE.Vector3(2, 2, 2));
  scene.add(group);

  let step = 0;
  const controls = setupControls();

  render();

  function render() {
    group.rotation.y = step += controls.rotationSpeed;
    group.rotation.z = step -= controls.rotationSpeed;
    group.rotation.x = step += controls.rotationSpeed;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      rotationSpeed: 0.01,
    };

    gui.add(controls, "rotationSpeed", 0, 0.5);

    return controls;
  }
</script>

MeshDepthMaterial

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();
  // 深度网格材质 一种按深度绘制几何体的材质。深度基于相机远近平面。白色最近,黑色最远。
  scene.overrideMaterial = new THREE.MeshDepthMaterial();

  const camera = initPerspectiveCamera({ near: 50, far: 120 });
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  const controls = setupControls();
  addMaterialSettings(gui, controls, scene.overrideMaterial);

  let i = 0;
  while (i < 10) {
    controls.addCube();
    i++;
  }

  render();

  function render() {
    scene.traverse(function (e) {
      if (e instanceof THREE.Mesh) {
        e.rotation.x += controls.rotationSpeed;
        e.rotation.y += controls.rotationSpeed;
        e.rotation.z += controls.rotationSpeed;
      }
    });

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      cameraNear: camera.near,
      cameraFar: camera.far,
      rotationSpeed: 0.02,
      removeCube: function () {
        const allChildren = scene.children;
        const lastObject = allChildren[allChildren.length - 1];
        if (lastObject instanceof THREE.Mesh) {
          scene.remove(lastObject);
          this.numberOfObjects = scene.children.length;
        }
      },
      addCube: function () {
        const cubeSize = Math.ceil(3 + Math.random() * 3);
        const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
        const cubeMaterial = new THREE.MeshLambertMaterial({
          color: Math.random() * 0xffffff,
        });
        const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.castShadow = true;

        cube.position.x = -60 + Math.round(Math.random() * 100);
        cube.position.y = Math.round(Math.random() * 10);
        cube.position.z = -100 + Math.round(Math.random() * 150);

        scene.add(cube);
        this.numberOfObjects = scene.children.length;
      },
    };

    const spGui = gui.addFolder("MeshDepthMaterial");
    spGui.add(scene.overrideMaterial, "wireframe");
    spGui.add(scene.overrideMaterial, "wireframeLinewidth", 0, 20);

    gui.add(controls, "rotationSpeed", 0, 0.5);
    gui.add(controls, "addCube");
    gui.add(controls, "removeCube");
    gui.add(controls, "cameraNear", 0, 100).onChange(function (e) {
      camera.near = e;
      camera.updateProjectionMatrix();
    });
    gui.add(controls, "cameraFar", 50, 200).onChange(function (e) {
      camera.far = e;
      camera.updateProjectionMatrix();
    });

    return controls;
  }
</script>

 

结合其它材质使用

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { createMultiMaterialObject } from "three/addons/utils/SceneUtils.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera({ near: 50, far: 120 });
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  const colorMaterial = new THREE.MeshBasicMaterial({
    color: 0x00ff00,
    transparent: true,
    blending: THREE.MultiplyBlending,
  });

  const controls = setupControls();

  let i = 0;
  while (i < 10) {
    controls.addCube();
    i++;
  }

  render();

  function render() {
    scene.traverse(function (e) {
      if (e instanceof THREE.Mesh) {
        e.rotation.x += controls.rotationSpeed;
        e.rotation.y += controls.rotationSpeed;
        e.rotation.z += controls.rotationSpeed;
      }
    });

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: colorMaterial.color.getStyle(),
      cameraNear: camera.near,
      cameraFar: camera.far,
      rotationSpeed: 0.02,
      removeCube: function () {
        const allChildren = scene.children;
        const lastObject = allChildren[allChildren.length - 1];
        if (lastObject instanceof THREE.Mesh) {
          scene.remove(lastObject);
        }
      },
      addCube: function () {
        const cubeSize = Math.ceil(3 + Math.random() * 3);
        const cubeGeometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
        const cubeMaterial = new THREE.MeshDepthMaterial();
        const cube = createMultiMaterialObject(cubeGeometry, [colorMaterial, cubeMaterial]);
        cube.castShadow = true;
        cube.position.x = -60 + Math.round(Math.random() * 100);
        cube.position.y = Math.round(Math.random() * 10);
        cube.position.z = -100 + Math.round(Math.random() * 150);

        scene.add(cube);
      },
    };

    gui.addColor(controls, "color").onChange(function (e) {
      colorMaterial.color.set(e);
    });
    gui.add(controls, "rotationSpeed", 0, 0.5);
    gui.add(controls, "addCube");
    gui.add(controls, "removeCube");
    gui.add(controls, "cameraNear", 0, 100).onChange(function (e) {
      camera.near = e;
      camera.updateProjectionMatrix();
    });
    gui.add(controls, "cameraFar", 50, 200).onChange(function (e) {
      camera.far = e;
      camera.updateProjectionMatrix();
    });

    return controls;
  }
</script>

 

 MeshLambertMaterial

 

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  // Lambert网格材质,一种非光泽表面的材质,没有镜面高光。
  // emissive : Color 材质的放射(光)颜色,基本上是不受其他光照影响的固有颜色。默认为黑色
  const meshMaterial = new THREE.MeshLambertMaterial({
    color: 0x7777ff,
  });
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: meshMaterial.color.getStyle(),
      emissive: meshMaterial.emissive.getHex(),

      selectedMesh: "cube",
      select: null,
    };

    addMaterialSettings(gui, controls, meshMaterial);

    const spGui = gui.addFolder("MeshLambertMaterial");
    spGui.addColor(controls, "color").onChange(function (e) {
      meshMaterial.color.setStyle(e);
    });
    spGui.addColor(controls, "emissive").onChange(function (e) {
      meshMaterial.emissive = new THREE.Color(e);
    });
    spGui.add(meshMaterial, "wireframe");
    spGui.add(meshMaterial, "wireframeLinewidth", 0, 20);

    return controls;
  }
</script>

 

MeshPhongMaterial

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  // Phong网格材质,一种用于具有镜面高光的光泽表面的材质。
  // emissive : Color 材质的放射(光)颜色,基本上是不受其他光照影响的固有颜色。默认为黑色
  // specular : Color 材质的高光颜色。默认值为0x111111(深灰色)的颜色Color。
  // shininess : Float  specular高亮的程度,越高的值越闪亮。默认值为 30。
  const meshMaterial = new THREE.MeshPhongMaterial({
    color: 0x7777ff,
  });
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: meshMaterial.color.getStyle(),
      emissive: meshMaterial.emissive.getStyle(),
      specular: meshMaterial.emissive.getStyle(),

      selectedMesh: "cube",
      select: null,
    };

    addMaterialSettings(gui, controls, meshMaterial);

    const spGui = gui.addFolder("MeshPhongMaterial");
    spGui.addColor(controls, "color").onChange(function (e) {
      meshMaterial.color.setStyle(e);
    });
    spGui.addColor(controls, "emissive").onChange(function (e) {
      meshMaterial.emissive = new THREE.Color(e);
    });
    spGui.addColor(controls, "specular").onChange(function (e) {
      meshMaterial.specular = new THREE.Color(e);
    });
    spGui.add(meshMaterial, "shininess", 0, 100);
    spGui.add(meshMaterial, "wireframe");
    spGui.add(meshMaterial, "wireframeLinewidth", 0, 20);

    return controls;
  }
</script>

 

 MeshNormalMaterial

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  //法线网格材质 一种把法向量映射到RGB颜色的材质。
  const meshMaterial = new THREE.MeshNormalMaterial();
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      selectedMesh: "cube",
      select: null,
    };

    addMaterialSettings(gui, controls, meshMaterial);

    return controls;
  }
</script>

 

MeshToonMaterial

 

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  // 一种实现卡通着色的材质。
  // emissive : Color 材质的放射(光)颜色,基本上是不受其他光照影响的固有颜色。默认为黑色
  const meshMaterial = new THREE.MeshToonMaterial({
    color: 0x7777ff,
  });
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: meshMaterial.color.getStyle(),
      emissive: meshMaterial.emissive.getStyle(),

      selectedMesh: "cube",
      select: null,
    };

    addMaterialSettings(gui, controls, meshMaterial);

    const spGui = gui.addFolder("MeshToonMaterial");
    spGui.addColor(controls, "color").onChange(function (e) {
      meshMaterial.color.setStyle(e);
    });
    spGui.addColor(controls, "emissive").onChange(function (e) {
      meshMaterial.emissive = new THREE.Color(e);
    });
    spGui.add(meshMaterial, "wireframe");
    spGui.add(meshMaterial, "wireframeLinewidth", 0, 20);

    return controls;
  }
</script>

 

MeshStandardMaterial

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  // 标准网格材质,一种基于物理的标准材质。
  // 在实践中,该材质提供了比MeshLambertMaterial 或MeshPhongMaterial 更精确和逼真的结果,代价是计算成本更高。
  // emissive : Color 材质的放射(光)颜色,基本上是不受其他光照影响的固有颜色。默认为黑色
  // metalness : Float 材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。
  // roughness : Float 材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。默认值为1.0。
  const meshMaterial = new THREE.MeshStandardMaterial({
    color: 0x7777ff,
  });
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: meshMaterial.color.getStyle(),
      emissive: meshMaterial.emissive.getStyle(),

      selectedMesh: "cube",
      select: null,
    };

    addMaterialSettings(gui, controls, meshMaterial);

    const spGui = gui.addFolder("MeshStandardMaterial");
    spGui.addColor(controls, "color").onChange(function (e) {
      meshMaterial.color.setStyle(e);
    });
    spGui.addColor(controls, "emissive").onChange(function (e) {
      meshMaterial.emissive = new THREE.Color(e);
    });
    spGui.add(meshMaterial, "metalness", 0, 1, 0.01);
    spGui.add(meshMaterial, "roughness", 0, 1, 0.01);
    spGui.add(meshMaterial, "wireframe");
    spGui.add(meshMaterial, "wireframeLinewidth", 0, 20);

    return controls;
  }
</script>

MeshPhysicalMaterial

<canvas id="mainCanvas"></canvas>
<script type="importmap">
  {
    "imports": {
      "three": "./js/build/three.module.js",
      "three/addons/": "./js/jsm/"
    }
  }
</script>
<script type="module">
  import * as THREE from "three";
  import { GUI } from "three/addons/libs/lil-gui.module.min.js";
  import { initRenderer, initPerspectiveCamera, initAmbientLight, initSpotLight, addMaterialSettings, addMaterialObjects } from "./init.js";

  const gui = new GUI();

  const renderer = initRenderer("mainCanvas");

  const scene = new THREE.Scene();

  const camera = initPerspectiveCamera();
  scene.add(camera);

  const ambienLight = initAmbientLight();
  scene.add(ambienLight);

  const spotLight = initSpotLight();
  scene.add(spotLight);

  const axesHelper = new THREE.AxesHelper(150);
  scene.add(axesHelper);

  // 物理网格材质
  // 物理网格材质使用了更复杂的着色器功能,所以在每个像素的渲染都要比three.js中的其他材质更费性能
  // emissive : Color 材质的放射(光)颜色,基本上是不受其他光照影响的固有颜色。默认为黑色
  // metalness : Float 材质与金属的相似度。非金属材质,如木材或石材,使用0.0,金属使用1.0,通常没有中间值。 默认值为0.0。
  // roughness : Float 材质的粗糙程度。0.0表示平滑的镜面反射,1.0表示完全漫反射。默认值为1.0。
  // clearcoat : Float 表示clear coat层的强度,范围从0.0到1.0m,当需要在表面加一层薄薄的半透明材质的时候,可以使用与clear coat相关的属性,默认为0.0;
  // clearcoatRoughness : Float clear coat层的粗糙度,由0.0到1.0。 默认为0.0
  // reflectivity : Float 反射率,由0.0到1.0。默认为0.5, 相当于折射率1.5。这模拟了非金属材质的反射率。当metalness为1.0时,此属性无效。
  const meshMaterial = new THREE.MeshPhysicalMaterial({
    color: 0x7777ff,
  });
  const controls = setupControls();
  addMaterialObjects(scene, gui, controls, meshMaterial);

  let step = 0;

  render();

  function render() {
    step += 0.01;
    controls.select.rotation.y = step;

    requestAnimationFrame(render);
    renderer.render(scene, camera);
  }

  function setupControls() {
    const controls = {
      color: meshMaterial.color.getStyle(),
      emissive: meshMaterial.emissive.getStyle(),

      selectedMesh: "cube",
      select: null,
    };

    addMaterialSettings(gui, controls, meshMaterial);

    const spGui = gui.addFolder("MeshPhysicalMaterial");
    spGui.addColor(controls, "color").onChange(function (e) {
      meshMaterial.color.setStyle(e);
    });
    spGui.addColor(controls, "emissive").onChange(function (e) {
      meshMaterial.emissive = new THREE.Color(e);
    });
    spGui.add(meshMaterial, "metalness", 0, 1, 0.01);
    spGui.add(meshMaterial, "roughness", 0, 1, 0.01);
    spGui.add(meshMaterial, "clearCoat", 0, 1, 0.01);
    spGui.add(meshMaterial, "clearCoatRoughness", 0, 1, 0.01);
    spGui.add(meshMaterial, "reflectivity", 0, 1, 0.01);
    spGui.add(meshMaterial, "wireframe");
    spGui.add(meshMaterial, "wireframeLinewidth", 0, 20);

    return controls;
  }
</script>

 

posted @ 2024-05-23 16:46  carol2014  阅读(10)  评论(0编辑  收藏  举报