Paint cube faces as a whole, not the triangles that make up the face - three.js

末鹿安然 提交于 2019-12-04 16:50:38

If you switch to BufferGeometry you can use groups to control the material of sections of your geometry. Groups are based on the vertex indices, and allow you to define a material index, which will reference a material inside an array of materials.

Consider:

// start, count, material index
bufferGeometry.addGroup(12, 6, 2)

This tells the geometry to start a new group of triangles at indices index 12, and accounts for 6 indices (which reference 6 vertices). The final parameter tells the group of triangles to use material index 2 (index 2 of the array of materials you use to create the mesh).

In the example below, I've given each side of a cube a different color. You might think this is the same effect as setting face colors, but note that this is setting a material per group, not just a color, which can lead to creating some really cool effects.

var renderer, scene, camera, controls, stats, mesh;

var WIDTH = window.innerWidth,
  HEIGHT = window.innerHeight,
  FOV = 35,
  NEAR = 1,
  FAR = 1000;

function populateScene() {
  var bg = new THREE.BufferGeometry();
  bg.addAttribute("position", new THREE.BufferAttribute(new Float32Array([
    // front
    -1, 1, 1, // 0
    -1, -1, 1, // 1
    1, 1, 1, // 2
    1, -1, 1, // 3
    // right
    1, 1, 1, // 4
    1, -1, 1, // 5
    1, 1, -1, // 6
    1, -1, -1, // 7
    // back
    1, 1, -1, // 8
    1, -1, -1, // 9
    -1, 1, -1, // 10
    -1, -1, -1, // 11
    // left
    -1, 1, -1, // 12
    -1, -1, -1, // 13
    -1, 1, 1, // 14
    -1, -1, 1, // 15
    // top
    -1, 1, -1, // 16
    -1, 1, 1, // 17
    1, 1, -1, // 18
    1, 1, 1, // 19
    // bottom
    -1, -1, 1, // 20
    -1, -1, -1, // 21
    1, -1, 1, // 22
    1, -1, -1 // 23
  ]), 3));
  bg.addAttribute("normal", new THREE.BufferAttribute(new Float32Array([
    // front
    0, 0, 1, // 0
    0, 0, 1, // 1
    0, 0, 1, // 2
    0, 0, 1, // 3
    // right
    1, 0, 0, // 4
    1, 0, 0, // 5
    1, 0, 0, // 6
    1, 0, 0, // 7
    // back
    0, 0, -1, // 8
    0, 0, -1, // 9
    0, 0, -1, // 10
    0, 0, -1, // 11
    // left
    -1, 0, 0, // 12
    -1, 0, 0, // 13
    -1, 0, 0, // 14
    -1, 0, 0, // 15
    // top
    0, 1, 0, // 16
    0, 1, 0, // 17
    0, 1, 0, // 18
    0, 1, 0, // 19
    // bottom
    0, -1, 0, // 20
    0, -1, 0, // 21
    0, -1, 0, // 22
    0, -1, 0 // 23
  ]), 3));
  bg.setIndex(new THREE.BufferAttribute(new Uint32Array([
    // front 0
    0, 1, 2,
    3, 2, 1,
    // right 6
    4, 5, 6,
    7, 6, 5,
    // back 12
    8, 9, 10,
    11, 10, 9,
    // left 18
    12, 13, 14,
    15, 14, 13,
    // top 24
    16, 17, 18,
    19, 18, 17,
    // bottom 30
    20, 21, 22,
    23, 22, 21
  ]), 1));
  
  bg.clearGroups();
  // start, count, material index
  bg.addGroup(0, 6, 0);
  bg.addGroup(6, 6, 1);
  bg.addGroup(12, 6, 2);
  bg.addGroup(18, 6, 3);
  bg.addGroup(24, 6, 4);
  bg.addGroup(30, 6, 5);
  
  var materials = [
    new THREE.MeshLambertMaterial({color:"red"}),
    new THREE.MeshLambertMaterial({color:"green"}),
    new THREE.MeshLambertMaterial({color:"blue"}),
    new THREE.MeshLambertMaterial({color:"cyan"}),
    new THREE.MeshLambertMaterial({color:"magenta"}),
    new THREE.MeshLambertMaterial({color:"yellow"})
  ];
  
  mesh = new THREE.Mesh(bg, materials);
  mesh.scale.set(5, 5, 5);
  
  scene.add(mesh);
}

function init() {
  document.body.style.backgroundColor = "slateGray";

  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
  });
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;

  document.body.appendChild(renderer.domElement);
  document.body.style.overflow = "hidden";
  document.body.style.margin = "0";
  document.body.style.padding = "0";

  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
  camera.position.z = 50;
  scene.add(camera);

  controls = new THREE.TrackballControls(camera, renderer.domElement);
  controls.dynamicDampingFactor = 0.5;
  controls.rotateSpeed = 3;

  var light = new THREE.PointLight(0xffffff, 1, Infinity);
  camera.add(light);

  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.top = '0';
  document.body.appendChild(stats.domElement);

  resize();
  window.onresize = resize;

  populateScene();

  animate();
}

function resize() {
  WIDTH = window.innerWidth;
  HEIGHT = window.innerHeight;
  if (renderer && camera && controls) {
    renderer.setSize(WIDTH, HEIGHT);
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
    controls.handleResize();
  }
}

function render() {
  renderer.render(scene, camera);
}

function animate() {
  mesh.rotation.x += 0.015;
  mesh.rotation.y += 0.017;
  mesh.rotation.z += 0.019;
  requestAnimationFrame(animate);
  render();
  controls.update();
  stats.update();
}

function threeReady() {
  init();
}

(function() {
  function addScript(url, callback) {
    callback = callback || function() {};
    var script = document.createElement("script");
    script.addEventListener("load", callback);
    script.setAttribute("src", url);
    document.head.appendChild(script);
  }

  addScript("https://threejs.org/build/three.js", function() {
    addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
      addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
        threeReady();
      })
    })
  })
})();

Edit: Adding a second example using the base BoxBufferGeometry

Based on pailhead's comment to the original post, here's a snippet which uses unmodified BoxBufferGeometry. But as they mentioned in their comment, you'll still need to know which group corresponds to which face.

var renderer, scene, camera, controls, stats, mesh;

var WIDTH = window.innerWidth,
  HEIGHT = window.innerHeight,
  FOV = 35,
  NEAR = 1,
  FAR = 1000;

function populateScene() {
  var bg = new THREE.BoxBufferGeometry(1, 1, 1);
  
  var materials = [
    new THREE.MeshLambertMaterial({color:"red"}),
    new THREE.MeshLambertMaterial({color:"green"}),
    new THREE.MeshLambertMaterial({color:"blue"}),
    new THREE.MeshLambertMaterial({color:"cyan"}),
    new THREE.MeshLambertMaterial({color:"magenta"}),
    new THREE.MeshLambertMaterial({color:"yellow"})
  ];
  
  mesh = new THREE.Mesh(bg, materials);
  mesh.scale.set(10, 10, 10);
  
  scene.add(mesh);
}

function init() {
  document.body.style.backgroundColor = "slateGray";

  renderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true
  });
  renderer.shadowMap.enabled = true;
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;

  document.body.appendChild(renderer.domElement);
  document.body.style.overflow = "hidden";
  document.body.style.margin = "0";
  document.body.style.padding = "0";

  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(FOV, WIDTH / HEIGHT, NEAR, FAR);
  camera.position.z = 50;
  scene.add(camera);

  controls = new THREE.TrackballControls(camera, renderer.domElement);
  controls.dynamicDampingFactor = 0.5;
  controls.rotateSpeed = 3;

  var light = new THREE.PointLight(0xffffff, 1, Infinity);
  camera.add(light);

  stats = new Stats();
  stats.domElement.style.position = 'absolute';
  stats.domElement.style.top = '0';
  document.body.appendChild(stats.domElement);

  resize();
  window.onresize = resize;

  populateScene();

  animate();
}

function resize() {
  WIDTH = window.innerWidth;
  HEIGHT = window.innerHeight;
  if (renderer && camera && controls) {
    renderer.setSize(WIDTH, HEIGHT);
    camera.aspect = WIDTH / HEIGHT;
    camera.updateProjectionMatrix();
    controls.handleResize();
  }
}

function render() {
  renderer.render(scene, camera);
}

function animate() {
  mesh.rotation.x += 0.015;
  mesh.rotation.y += 0.017;
  mesh.rotation.z += 0.019;
  requestAnimationFrame(animate);
  render();
  controls.update();
  stats.update();
}

function threeReady() {
  init();
}

(function() {
  function addScript(url, callback) {
    callback = callback || function() {};
    var script = document.createElement("script");
    script.addEventListener("load", callback);
    script.setAttribute("src", url);
    document.head.appendChild(script);
  }

  addScript("https://threejs.org/build/three.js", function() {
    addScript("https://threejs.org/examples/js/controls/TrackballControls.js", function() {
      addScript("https://threejs.org/examples/js/libs/stats.min.js", function() {
        threeReady();
      })
    })
  })
})();
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!