我想用不同的材质合并两个网格。
这是我所做的,但是渲染不正确,就像渲染对象的一侧一样。
这是我在codeandbox上的代码:
https://codesandbox.io/s/summer-dawn-5nq05?fontsize=14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script>
let renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Scene
let scene = new THREE.Scene();
scene.background = new THREE.Color(0xcce0ff);
// Camera
let camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
camera.position.set(30, 0, 100);
let controls = new THREE.OrbitControls(camera);
for (let i = 0; i < 1; i++) {
// Geometry
let cube1Geometry = new THREE.PlaneGeometry(10, 10, 10);
let cube2Geometry = new THREE.PlaneGeometry(10, 15, 5);
// Material
let cube1Material = new THREE.MeshStandardMaterial({
color: 0x7c3c3c,
roughness: 1
});
let cube2Material = new THREE.MeshStandardMaterial({
color: 0x01b8ba,
roughness: 0.1
});
// Mesh
let cube1 = new THREE.Mesh(cube1Geometry, cube1Material);
let cube2 = new THREE.Mesh(cube2Geometry, cube2Material);
// Combine
let singleGeometry = combine([cube1, cube2]);
let single = new THREE.Mesh(singleGeometry, [
cube1Material,
cube2Material
]);
// scene.add(cube1);
// scene.add(cube2);
scene.add(single);
single.position.set(
Math.random() * 5,
Math.random() * 10,
Math.random() * 20
);
}
function combine(meshes) {
let mergeGeometry = new THREE.Geometry();
for (let i = 0; i < meshes.length; i++) {
meshes[i].updateMatrix();
// update materialIndex
for (let j = 0; j < meshes[i].geometry.faces.length; j++) {
meshes[i].geometry.faces[j].materialIndex = 0;
}
mergeGeometry.merge(meshes[i].geometry, meshes[i].matrix, i);
}
return mergeGeometry;
}
// LIGHT
let light1 = new THREE.AmbientLight(0x666666);
scene.add(light1);
let light = new THREE.SpotLight(0xdfebff, 1);
light.position.set(50, 200, 100);
scene.add(light);
requestAnimationFrame(function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
});
</script>
</body>
</html>
答案 0 :(得分:1)
之所以会发生此行为,是因为BoxGeometry
(source)为每个faces规定了不同的MaterialIndex
。反过来,当使用一系列材料时,这又控制了要用于该面的材料。
要确保每个几何只使用数组中指定的材料,您需要将几何的每个面从MaterialIndex
重置为0
。这样,geometry.merge()
将正确调整每个几何形状以使用正确的材质。
我已经修改了您的combine
函数以即时执行此操作。我不确定是否有更好的方法来重置MaterialIndex
,至少我找不到任何方法。
function combine(meshes) {
let mergeGeometry = new THREE.Geometry();
for (let i = 0; i < meshes.length; i++) {
meshes[i].updateMatrix();
// update materialIndex
for ( let j = 0; j < meshes[i].geometry.faces.length; j++ ) {
meshes[i].geometry.faces[j].materialIndex = 0;
}
mergeGeometry.merge( meshes[i].geometry, meshes[i].matrix, i );
}
return mergeGeometry;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<style>
body {
margin: 0;
position: fixed;
}
canvas {
width: 100%;
height: 100%;
display: block;
}
</style>
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
</head>
<body>
<script>
let renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// Scene
let scene = new THREE.Scene();
scene.background = new THREE.Color(0xcce0ff);
// Camera
let camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
1,
1000
);
camera.position.set(30, 0, 50);
let controls = new THREE.OrbitControls(camera);
// Geometry
let cube1Geometry = new THREE.BoxGeometry(10, 10, 10);
let cube2Geometry = new THREE.BoxGeometry(10, 15, 5);
// Material
let cube1Material = new THREE.MeshStandardMaterial({
color: 0x7c3c3c,
roughness: 1
});
let cube2Material = new THREE.MeshStandardMaterial({
color: 0x01b8ba,
roughness: 0.1
});
// Mesh
let cube1 = new THREE.Mesh(cube1Geometry, cube1Material);
let cube2 = new THREE.Mesh(cube2Geometry, cube2Material);
// Combine
let singleGeometry = combine([cube1, cube2]);
let single = new THREE.Mesh(singleGeometry, [
cube1Material,
cube2Material
]);
scene.add(single);
function combine(meshes) {
let mergeGeometry = new THREE.Geometry();
for (let i = 0; i < meshes.length; i++) {
meshes[i].updateMatrix();
// update materialIndex
for ( let j = 0; j < meshes[i].geometry.faces.length; j++ ) {
meshes[i].geometry.faces[j].materialIndex = 0;
}
mergeGeometry.merge( meshes[i].geometry, meshes[i].matrix, i );
}
return mergeGeometry;
}
// LIGHT
let light1 = new THREE.AmbientLight(0x666666);
scene.add(light1);
let light = new THREE.SpotLight(0xdfebff, 1);
light.position.set(50, 200, 100);
scene.add(light);
requestAnimationFrame(function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
});
</script>
</body>
</html>