ThreeJS:更好的方法来创建和渲染单个树木的森林?

lea*_*lay 5 javascript three.js

我试图在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);
Run Code Online (Sandbox Code Playgroud)

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

way*_*boy 5

如何使用广告牌渲染树木?广告牌的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
});
Run Code Online (Sandbox Code Playgroud)