最小化 Three.js 绘制的次数
我正在测试 Three.js 在我的项目中的使用 (http://agentscript.org) 和第一个测试似乎很慢:
I'm testing the use of Three.js for my project (http://agentscript.org) and the first test seems quite slow:
https://asx-vqnhxlahpe.now.sh/test.html?three0
(注意:该网站可能需要一段时间,在一段时间不使用后它会休眠")
(note: the site can take a while, it "sleeps" after a period of non-use)
这显然是由于我使用了太多的平局,每个代理一个.renderer.info.render对象 {calls: 10002, vertices: 60090, faces: 20000, points: 0}
This is apparently due to my using way too many draws, one per agent.
renderer.info.render
Object {calls: 10002, vertices: 60090, faces: 20000, points: 0}
我相信使用 BufferGeometry 可以解决这个问题,但我不知道如何使用它并且仍然能够访问每个单独的代理,以便我的 step/animate 函数可以修改(移动、旋转)它们.
I believe using a BufferGeometry would solve this, but I don't know how to use one and still be able to access each individual agent so that my step/animate function can modify (move, rotate) them.
我该怎么做?
我意识到我可以简单地使用我自己的着色器,并计划这样做,但我更喜欢先有一个或两个中间解决方案.
I realize I could simply go to using my own Shader, and plan to do so, but I'd prefer to have an intermediate solution or two first.
您希望减少 Agent 模拟中的绘制调用次数,并使某些工作相对轻松.您可以将您的代理集合表示为 THREE.Points
.
You want to reduce the number of draw calls in your Agent simulation and get something working relatively easily. You can do that by representing your collection of agents as THREE.Points
.
// geometry
var geometry = new THREE.BufferGeometry();
// attributes
var positions = new Float32Array( numAgents * 3 ); // 3 values per vertex
var rotations = new Float32Array( numAgents * 1 ); // 1 values per vertex
for ( var i = 0; i < numAgents; i ++ ) {
positions[ i ] = 0;
positions[ i + 1 ] = 0;
positions[ i + 2 ] = 0;
rotations[ i ] = 2 * Math.PI * Math.random();
}
geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
geometry.addAttribute( 'rotation', new THREE.BufferAttribute( rotations, 1 ) );
// material
var material = new THREE.PointsMaterial( {
color: 0xff0000,
size: 4,
map: null
} );
// points
points = new THREE.Points( geometry, material );
scene.add( points );
这将在单个绘制调用中呈现,您可以更新 CPU 上的位置并将数据每帧推送到 GPU.您应该能够轻松渲染 100,000 个代理.
This will render in a single draw call and you can update the positions on the CPU and push the data to the GPU each frame. You should be able to render 100,000 agents easily.
小提琴:http://jsfiddle.net/730ffn4x/
如果要将点表示为带方向的箭头,则需要提供带有箭头图像的纹理和自定义 ShaderMaterial
以旋转每个点.
If you want to represent your points as an arrow with direction, you would need to provide texture with an arrow image and a custom ShaderMaterial
to rotate each point.
InstancedBufferGeometry
适用于每个代理必须表示为 Mesh
的情况.这是@MartinSchuhfuß 的一个很好的例子,与您想要做的类似.
InstancedBufferGeometry
is appropriate if each agent must be represented as a Mesh
. Here is a fine example by @MartinSchuhfuß that is similar to what you want to do.
对于激烈的模拟,您可以使用 GPGPU.查看three.js 示例.在 GPGPU 中,模拟完全在 GPU 上运行,而 CPU 通常只做最少的工作.
For intense simulations, you would use GPGPU. See the three.js examples. In GPGPU, the simulation runs entirely on the GPU, and the CPU typically does minimal work.
three.js r.84
three.js r.84