8

我正在尝试在 ThreeJS 中渲染一个由 100,000 多棵非常简单的树组成的大森林。创建许多单独的网格当然是不可能的。我当前的方法使用 GeometryUtils.merge 创建一个大型几何图形,从而减少了绘制调用的数量,并且效果很好。但是接近100k,它陷入困境。我需要进一步提高性能,我感觉可能还有一两个技巧可以将性能提高 10 倍或更多。

代码如下,我还创建了一个 JSFiddle 来展示我当前的技术:http: //jsfiddle.net/RLtNL/

//tree geometry (two intersecting y-perpendicular triangles)
var triangle = new THREE.Shape();
triangle.moveTo(5, 0);
triangle.lineTo(0, 12);
triangle.lineTo(-5, 0);
triangle.lineTo(5, 0);
var tree_geometry1 = new THREE.ShapeGeometry(triangle);

var matrix = new THREE.Matrix4();
var tree_geometry2 = new THREE.ShapeGeometry(triangle);
tree_geometry2.applyMatrix(matrix.makeRotationY(Math.PI / 2));


//tree material
var basic_material = new THREE.MeshBasicMaterial({color: 0x14190f});
basic_material.color = new THREE.Color(0x14190f);
basic_material.side = THREE.DoubleSide;


//merge into giant geometry for max efficiency
var forest_geometry = new THREE.Geometry();
var dummy = new THREE.Mesh();
for (var i = 0; i < 1000; i++) 
{
    dummy.position.x = Math.random() * 1000 - 500;
    dummy.position.z = Math.random() * 1000 - 500;
    dummy.position.y = 0;

    dummy.geometry = tree_geometry1;
    THREE.GeometryUtils.merge(forest_geometry, dummy);

    dummy.geometry = tree_geometry2;
    THREE.GeometryUtils.merge(forest_geometry, dummy);
}


//create mesh and add to scene
var forest_mesh = new THREE.Mesh(forest_geometry, basic_material);
scene.add(forest_mesh);

任何人都可以建议进一步的技术来使这种加载和渲染更快吗?

4

1 回答 1

6

使用广告牌来渲染树木怎么样?广告牌的 2D 特性似乎适合这个特殊问题。创建具有透明度的简单 png 树纹理,并将每棵树添加为 PointCloud 对象 - http://threejs.org/docs/#Reference/Objects/PointCloud

大多数低端显卡可以渲染超过 10,000 个广告牌对象而不会降低帧率。我已经使用广告牌技术更新了您的代码(将树的数量更改为 10,000 并使用 100 像素高的树纹理):http: //jsfiddle.net/wayfarer_boy/RLtNL/8/ - 以下代码的摘录:

geometry = new THREE.Geometry();
sprite = new THREE.Texture(image);
sprite.needsUpdate = true;
for (var i = 0; i < 10000; i++) {
    var vertex = new THREE.Vector3();
    vertex.x = Math.random() * 1000 - 500;
    vertex.y = 0;
    vertex.z = Math.random() * 1000 - 500;
    geometry.vertices.push(vertex);
}
material = new THREE.PointCloudMaterial({
    size: 50,
    sizeAttenuation: true,
    map: sprite,
    transparent: true,
    alphaTest: 0.5
});
particles = new THREE.PointCloud(geometry, material);
// particles.sortParticles = true;
// Removed line above and using material.alphaTest instead
// Thanks @WestLangley
scene.add(particles);
renderer = new THREE.WebGLRenderer({
    clearAlpha: 1,
    alpha: true
});
于 2015-01-14T22:02:12.803 回答