根据three.js github上的各种帖子,MeshFaceMaterial最终将被弃用。

我目前将此用于我的地形。当然,这不是最好的方法。其实它很烂。对于一个我不能使用BufferGeometry不好,考虑到我通常有两层128x128(分段的)平面用于地形。内存使用率很高。

我修改了我所有的代码,以使地形成为BufferGeometry,除非有两件事不起作用。 MeshFaceMaterialBufferGeometry.merge()。考虑到三个创建了该几何体,合并对索引的几何体不起作用,我认为这很奇怪,但是它可以合并来自Blender的非索引几何体。它不能合并自己创建的几何图形,但可以合并来自外部源的几何图形...哦,那是另一篇帖子,回到MeshFaceMaterial

我目前使用的是128x128的“ MaterialMap”。每个像素代表该平面每个面的materialIndex。这有两个严重的缺点。地形的平方部分(无曲线)和纹理边界的严格区分。

我的问题是:如何在不使用MeshFaceMaterial的情况下生成具有多个纹理的地形。我拥有的最高分辨率纹理为2048x2048,区域大小可以轻松为10000x10000,因此有必要重复(对吗?)。

最终,我的目标是使用BufferGeometry并摆脱MeshFaceMaterial

MaterialMap示例:

地形示例(非常抱歉{work pc}):

最佳答案

您前段时间通过电子邮件为我提供了有关剔除网孔的建议,以帮助我(希望以我谦逊的策略):)
如果要使用THREE.PlaneBufferGeometry(如您所知,这是THREE.js中所有几何图形的前进方向),那么我的建议是将不同的PlaneBufferGeometries相互叠加。例如,在上面的示例图片中,您可能有

var stoneFloorGeometry = new THREE.PlaneBufferGeometry(arenaWidth, arenaHeight, 1, 1);
var stoneFloorMaterial = new THREE.MeshBasicMaterial({
    depthWrite: false, // This is always underneath every other object
    map: stoneFloorTexture
});
var stoneFloor = new THREE.Mesh(stoneFloorGeometry, stoneFloorMaterial);
stoneFloor.rotation.x = Math.PI / -2; // rotate to be flat in the X-Z plane
stoneFloor.position.set(0, 0, 0);
scene.add(stoneFloor);

// now add the grass plane right on top of that with its own texture and shape

var grassGeometry = new THREE.PlaneBufferGeometry(lawnWidth, lawnHeight, 1, 1);
var grassMaterial = new THREE.MeshBasicMaterial({
    depthWrite: false, // this is rendered right on top of the stone floor
    map: grassTexture
});
var grass = new THREE.Mesh(grassGeometry, grassMaterial);
grass.rotation.x = Math.PI / -2;
grass.position.set(0, 0, 0);
scene.add(grass);

// finally add the stone path walkway on top of the grass, leading to the castle

var walkwayGeometry = new THREE.PlaneBufferGeometry(walkwayWidth, walkwayHeight, 1, 1);
var walkwayMaterial = new THREE.MeshBasicMaterial({
    depthWrite: false, // this is rendered right on top of the grass
    map: stoneFloorTexture // uses same texture as large stoneFloor before
});
var walkway = new THREE.Mesh(walkwayGeometry, walkwayMaterial);
walkway.rotation.x = Math.PI / -2;
walkway.position.set(0, 0, 0);
scene.add(walkway);

只要您从下到上对关卡进行分层并禁用depthWrite,所有各种纹理都将正确地显示在彼此的顶部,并且不会进行Z形战斗。因此,stoneFloor首先添加到场景中,然后是草,然后是人行道。
而且,由于depthTest仍处于活动状态,因此您正在移动的游戏角色将在所有这些各种纹理的顶部进行渲染。最初,它看起来也像只是禁用了“ depthTest”一样工作,但是纹理最终渲染(“上方”)了不正确的字符/模型。
最终,当THREE.js将ShapeGeometry移至BufferGeometry时,最好定义一个任意的多边形(例如八边形或其他形状),然后以类似的方式对游戏地图进行纹理贴图并在彼此之上放置形状,从而避免了您提到的“方形”问题。
对于当前的解决方案,在现代的CPU / GPU上,我认为创建3个PlaneBufferGeometries(而不是1个具有多个面/索引的大对象)不会看到很多性能成本。这样,您具有使用三个的BufferGeometry的优点,同时仍然使所有内容“看起来”都像是纹理映射到一个大平面上。
希望这可以帮助!
-Erich(GitHub上的erichlof)

10-07 22:47