最小化 Three.js 绘制的次数 [英] Minimizing number of Three.js Draws

查看:50
本文介绍了最小化 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

这篇关于最小化 Three.js 绘制的次数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆