在浏览器中展示400万个2D正方形,最有效的方法是什么?

5

我的显示器分辨率为7680x4320像素。我想展示多达400万个不同颜色的正方形,并且我想通过滑块来改变正方形的数量。目前我有两个版本。其中一个是使用canvas-fillRect,看起来像这样:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

for (var i = 0; i < num_squares; i ++) {

   ctx.fillStyle = someColor;
   ctx.fillRect(pos_x, pos_y, pos_x + square_width, pos_y + square_height);

   // set pos_x and pos_y for next square
}

我使用webGL和three.js创建了一个与之前相同的循环,但为每个正方形创建了一个盒子几何体和网格:

var geometry = new THREE.BoxGeometry( width_height, width_height, 0);

for (var i = 0; i < num_squares; i ++) {

   var material = new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } );
   material.emissive = new THREE.Color( Math.random(), Math.random(), Math.random() );

   var object = new THREE.Mesh( geometry, material );

}

这两个版本在几千平方米以内都运行得很好。第一个版本最多可以处理一百万个平方,但超过一百万后速度就非常慢了。我想实现动态更新颜色和平方数量。

有没有人有关于如何更有效地使用three.js/WebGL/Canvas的提示?

编辑1:第二个版本:这是我在开始时和滑块变化时所做的:

// Remove all objects from scene
            var obj, i;
            for ( i = scene.children.length - 1; i >= 0 ; i -- ) {
                obj = scene.children[ i ];
                if ( obj !== camera) {
                    scene.remove(obj);
                }
            }

            // Fill scene with new objects
            num_squares = gui_dat.squareNum;

            var window_pixel = window.innerWidth * window.innerHeight;
            var pixel_per_square = window_pixel / num_squares;
            var width_height = Math.floor(Math.sqrt(pixel_per_square));

            var geometry = new THREE.BoxGeometry( width_height, width_height, 0);

            var pos_x = width_height/2;
            var pos_y = width_height/2;

            for (var i = 0; i < num_squares; i ++) {

                //var object = new THREE.Mesh( geometry,  );

                var material = new THREE.Material()( { color: Math.random() * 0xffffff } );
                material.emissive = new THREE.Color( Math.random(), Math.random(), Math.random() );

                var object = new THREE.Mesh( geometry, material );

                object.position.x = pos_x;
                object.position.y = pos_y;

                pos_x += width_height;
                if (pos_x > window.innerWidth) {

                    pos_x = width_height/2;
                    pos_y += width_height;
                }

                scene.add( object );

            }

那 http://www.pixijs.com/ 怎么样?它是一个2D加速框架。 我认为400万对于今天的计算能力来说是一个非常巨大的数字... - SharpEdge
你使用 BoxGeometry 而不是 PlaneGeometry 或者甚至是 PlaneBufferGeometry,有什么原因吗? - gaitat
1
我不知道这是否有帮助,但无论如何都是一篇好文章:http://www.html5rocks.com/en/tutorials/webgl/million_letters/ - gaitat
2
在片段着色器中使用一个几何体完成所有工作? - Ben Gannaway
如果你只需要改变方块的数量,我认为使用webgl画布和片段着色器是最好的选择。不需要几何或Three.js。这里有一个教程可以帮助你完成大部分工作:http://www.html5rocks.com/en/tutorials/webgl/webgl_fundamentals/。 - 2pha
显示剩余14条评论
3个回答

3
用gl.POINTS原语并将gl_PointSize设置为像素大小是绘制正方形最快的方法。
在three.js中,gl.POINTS被包装在THREE.PointCloud对象中。您需要创建一个几何体对象,每个点都有一个位置,并将其传递给PointCloud构造函数。
以下是THREE.PointCloud实例的示例:http://codepen.io/seanseansean/pen/EaBZEY
geometry = new THREE.Geometry();

for (i = 0; i < particleCount; i++) {

    var vertex = new THREE.Vector3();
    vertex.x = Math.random() * 2000 - 1000;
    vertex.y = Math.random() * 2000 - 1000;
    vertex.z = Math.random() * 2000 - 1000;

    geometry.vertices.push(vertex);
}

...

materials[i] = new THREE.PointCloudMaterial({size:size});
particles = new THREE.PointCloud(geometry, materials[i]);

我没有深入研究所有代码,但我设置了粒子数量为2m,并且据我理解,会生成5个点云,因此2m * 5 = 10m颗粒,我得到的帧速率约为30fps。


2
到目前为止,我看到的个人点数最高的技术是potree。http://potree.org/https://github.com/potree。试用了一些演示,我能够以20-30fps的速度观察3D中的500万个点。我相信这也是当前的技术极限。
我没有亲自测试过potree,所以对这项技术不是很了解。但是有数据转换器和查看器(基于threejs),所以只需要弄清楚如何转换数据即可。
简要回答您的问题:处理大量数据的最佳方法是将它们分组为四叉树(2D)或八叉树(3D)。这将使您无需担心摄像机远离或完全不可见的部分。另一方面,程序不喜欢进行太多的WebGL调用。试着理解这样的情况,你想每秒创建约60张图像。但是每次设置GPU的某些参数时,程序必须进行一些同步。分割数据意味着您需要做更多的设置,因此树不能太详细。
最后一件事,有人说:
“你可能想把值数组作为着色器uniform之一传递。”
我不建议这样做,这是个坏主意。纹理查找非常快,但属性总是更快的。如果我们谈论4M个点,您无法负担从uniforms中读取数据。
抱歉,我无法帮您编写代码,我可以在没有threejs的情况下完成它,但我不是threejs专家 :)

0
我建议尝试使用Pixi框架(如上面的评论中提到的)。
它具有WebGL渲染器,一些基准测试非常有前途。

http://www.goodboydigital.com/pixijs/bunnymark_v3/

它可以处理很多动画精灵。 如果您的应用程序仅显示正方形,不进行动画处理,并且它们是非常简单的精灵(只有一种颜色),那么它将比上面的演示链接提供更好的性能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接