THREE.js:寻找MeshFaceMaterial的替代品

时间:2015-03-18 21:33:44

标签: three.js textures shader

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

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

我已经调整了所有代码以允许地形为BufferGeometry,除了两件事不起作用。 MeshFaceMaterialBufferGeometry.merge()。合并对索引几何不起作用,考虑到THREE创建了这个几何体,它对我来说很奇怪,但它可以合并来自blender的非索引几何。它不能合并它自己创建的几何体,但可以合并来自外部源的几何体......哦,那是另一个帖子,回到MeshFaceMaterial

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

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

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

MaterialMap示例:enter image description here

地形示例(非常裁剪抱歉{work pc}):enter image description here

1 个答案:

答案 0 :(得分:4)

你曾经通过电子邮件帮我解决了剔除网格的建议,所以我想回报一下(用我简单的策略):)

如果你想使用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仍处于活动状态,因此您移动的游戏角色将呈现在所有这些不同纹理之上。最初,看起来它只是禁用了“深度测试”,但纹理最终渲染('以上')不正确的字符/模型。

最后,当THREE.js将ShapeGeometry移动到BufferGeometry时,定义一个任意多边形形状(如八角形或其他东西)然后纹理贴图并将其形状放在彼此的顶部以获得游戏关卡将会很不错。以类似的方式,从而避免了方形'你提到的问题。

至于目前的解决方案,在现代CPU / GPU上我不认为你会在创建3个PlaneBufferGeometries而不是1个具有多个面/索引的大型数据时看到很多性能成本。通过这种方式,您可以使用THREE的BufferGeometry,同时仍然可以使用所有内容来查看'就像它是所有纹理映射到一个大平面。

希望这有帮助! -Erich(GitHub上的erichlof)