如何在每个面上渲染具有不同纹理的四面体(使用 three.js)?

how to render a tetrahedron with different texture on each face (using three.js)?

试了很多还是没解决..

如何在每个面上渲染具有不同纹理的四面体?

一开始我也是这么试的

import * as THREE from 'three';

window.onload = () => {
  const scene = new THREE.Scene()
  const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  const renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)
  document.body.appendChild(renderer.domElement)
  var geometry = new THREE.CylinderGeometry(0, 2, 3, 3, 3, false)
  var materials = [
    new THREE.MeshBasicMaterial({ color: 0xff00ff }),
    new THREE.MeshBasicMaterial({ color: 0xff0000 }),
    new THREE.MeshBasicMaterial({ color: 0x0000ff }),
    new THREE.MeshBasicMaterial({ color: 0x5100ff })
  ]


  var tetra = new THREE.Mesh(geometry, materials)
  scene.add(tetra)
  renderer.render(scene, camera)
  camera.position.z = 5;
  var ambientLight = new THREE.AmbientLight(0xffffff, 0.5)
  scene.add(ambientLight)

  function animate() {
    requestAnimationFrame(animate)
    tetra.rotation.x += 0.04;
    tetra.rotation.y += 0.04;
    renderer.render(scene, camera)
  }
  animate()
}

我使用圆柱几何体来“制作”一个假的四面体。

但我发现我无法为这个“四面体”的每个面都添加纹理,bc 圆柱体几何实际上只有 3 个面。

有人知道怎么做吗?

P.S。我也尝试过 TetrahedronGeometry,但它没有用,我猜这是因为 TetrahedronGeometry 基本上是 BufferGeometry,上面没有面 属性。

您可以构建自己的几何图形或修改现有几何图形。要在侧面使用不同的材质,请使用 groups.

body{
  overflow: hidden;
  margin: 0;
}
<script type="module">
import * as THREE from "https://cdn.skypack.dev/three@0.136.0";
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls"

let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.set(0, 5, 10).setLength(3);
let renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

window.addEventListener("resize", event => {
  camera.aspect = innerWidth / innerHeight;
  camera.updateProjectionMatrix();
  rendrer.setSize(innerWidth, innerHeight);
})

let controls = new OrbitControls(camera, renderer.domElement);

// https://discourse.threejs.org/t/tetrahedron-non-indexed-buffer-geometry/12542
// tetrahedron
// ---------------------------------------------------------------------------------------
var pts = [ // https://en.wikipedia.org/wiki/Tetrahedron#Coordinates_for_a_regular_tetrahedron
  new THREE.Vector3(Math.sqrt(8 / 9), 0, -(1 / 3)),
  new THREE.Vector3(-Math.sqrt(2 / 9), Math.sqrt(2 / 3), -(1 / 3)),
  new THREE.Vector3(-Math.sqrt(2 / 9), -Math.sqrt(2 / 3), -(1 / 3)),
  new THREE.Vector3(0, 0, 1)
];

var faces = [ // triangle soup
  pts[0].clone(), pts[2].clone(), pts[1].clone(),
  pts[0].clone(), pts[1].clone(), pts[3].clone(),
  pts[1].clone(), pts[2].clone(), pts[3].clone(),
  pts[2].clone(), pts[0].clone(), pts[3].clone()
];

var geom = new THREE.BufferGeometry().setFromPoints(faces);
geom.rotateX(-Math.PI * 0.5);
geom.computeVertexNormals();

geom.setAttribute("uv", new THREE.Float32BufferAttribute([ // UVs
  0.5, 1, 0.06698729810778059, 0.2500000000000001, 0.9330127018922194, 0.2500000000000001,
  0.06698729810778059, 0.2500000000000001, 0.9330127018922194, 0.2500000000000001, 0.5, 1,
  0.06698729810778059, 0.2500000000000001, 0.9330127018922194, 0.2500000000000001, 0.5, 1,
  0.06698729810778059, 0.2500000000000001, 0.9330127018922194, 0.2500000000000001, 0.5, 1
], 2));
geom.addGroup(0, 3, 0);
geom.addGroup(3, 3, 1);
geom.addGroup(6, 3, 2);
geom.addGroup(9, 3, 3);
// ---------------------------------------------------------------------------------------

let tl = new THREE.TextureLoader();
let tp = "https://threejs.org/examples/textures/";
let tetra = new THREE.Mesh(geom, [
  new THREE.MeshBasicMaterial({map: tl.load(tp + "uv_grid_opengl.jpg")}),
  new THREE.MeshBasicMaterial({map: tl.load(tp + "colors.png")}),
  new THREE.MeshBasicMaterial({map: tl.load(tp + "brick_diffuse.jpg")}),
  new THREE.MeshBasicMaterial({map: tl.load(tp + "758px-Canestra_di_frutta_(Caravaggio).jpg")})
])
scene.add(tetra);

renderer.setAnimationLoop(()=> {
  renderer.render(scene, camera);
});
</script>

我终于明白了如何使用 three.js TetrahedronGeometry.

让它工作

实际上没有必要制作我们自己的 geo,但是如果我们使用 three.js TetrahedronGeometry.

,我们将不得不重新设置 uv array

private initGeometry(){
    const radius = this.config.size*Math.sqrt(6)/4;
    this.geometry = new THREE.TetrahedronGeometry(radius,0);
    console.log(this.geometry.attributes.uv.array);
    this.geometry.addGroup(0, 3, 0);
    this.geometry.addGroup(3, 3, 1);
    this.geometry.addGroup(6, 3, 2);
    this.geometry.addGroup(9, 3, 3);
    this.geometry.setAttribute("uv", new THREE.Float32BufferAttribute([ // UVs, 
//numbers here are to describe uv coordinate, so they are actually customizable
// if you want to customize it, you have to check the vertices position array first. 
    0,0,
    1, 0,
    0.5, 1,
    //
    1, 0,
    0.5, 1, 
    0,0,
    //
    1, 0,
    0.5, 1,
    0,0,
    //
    0,0,
    1, 0,
    0.5, 1
  ], 2));
    this.geometry.rotateY(-Math.PI);
  }