8

ThreeJS で 100,000 以上の非常に単純な木の大きな森をレンダリングしようとしています。もちろん、多数の個別のメッシュを作成することは問題外です。私の現在の方法では、GeometryUtils.merge を使用して 1 つの大きなジオメトリを作成し、ドロー コールの数を減らしており、これはかなりうまく機能します。しかし、100kに近づくと、行き詰まります。パフォーマンスをさらに改善する必要があり、パフォーマンスをさらに 10 倍以上向上させるには、別のトリックが 1 つまたは 2 つあると感じています。

コードは以下にあり、現在のテクニックを示す 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 に答える