THREE.js:寻找 MeshFaceMaterial 的替代品

THREE.js: Looking for an alternative to MeshFaceMaterial

根据 three.js github 中的各种 post,MeshFaceMaterial 最终将被弃用。

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

我已经修改了所有代码以允许地形 BufferGeometry 除了有两点不起作用。 MeshFaceMaterialBufferGeometry.merge()。合并不适用于索引几何体,考虑到 THREE 创建了这个几何体,这对我来说很奇怪,但它可以合并来自搅拌机的非索引几何体。它不能合并它自己创建的几何体,但可以合并来自外部来源的几何体……哦,那是另一个 post,回到 MeshFaceMaterial

我目前使用 128x128 "MaterialMap"。每个像素代表平面的每个面的 materialIndex。这有两个严重的缺点。将地形部分(无曲线)平方和纹理边界上的粗糙区别。

我的问题是:如何在不使用 MeshFaceMaterial 的情况下生成具有多个纹理的地形。我拥有的最高分辨率纹理是 2048x2048,区域大小很容易达到 10000x10000,因此需要重复(对吧?)。

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

材质贴图示例:

地形示例(严重裁剪对不起{work pc}):

不久前你通过电子邮件帮助我解决了剔除网格的问题,所以我想 return 帮我一个忙(用我谦虚的策略):)

如果您想使用 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,所有不同的纹理就会正确地显示在彼此之上,并且 none 会出现 Z 冲突。因此,首先将 stoneFloor 添加到场景中,然后是草地,然后是走道。 由于 depthTest 仍处于活动状态,您移动的游戏角色将渲染在所有这些不同的纹理之上。最初,它看起来也只是禁用 'depthTest',但纹理最终渲染在 ('above') characters/models 上,这是不正确的。

最终当 THREE.js 将 ShapeGeometry 移至 BufferGeometry 时,最好定义任意多边形形状(如八边形或其他形状),然后对其进行纹理贴图并将形状相互重叠放置以类似的方式处理游戏关卡,从而避免了您提到的 'square' 问题。

至于当前的解决方案,在现代 CPU/GPU 上,我认为创建 3 个 PlaneBufferGeometries 而不是 1 个具有多个 faces/indexes 的大型 PlaneBufferGeometries 不会带来太多性能成本。通过这种方式,您可以利用 THREE 的 BufferGeometry 的优势,同时仍然拥有一切 'looking' 就像它全部纹理映射到一个大平面一样。

希望对您有所帮助! -Erich(GitHub 上的 erichlof)