【问题标题】:What is the most efficient way to display 4 million 2D squares in a browser?在浏览器中显示 400 万个 2D 正方形的最有效方法是什么?
【发布时间】:2015-07-19 12:40:19
【问题描述】:

我的显示器的分辨率为 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 );

}

对于几千个正方形,它们都工作得很好。第一个版本最多可以做 100 万个方格,但是超过 100 万个的所有内容都非常缓慢。我想动态更新颜色和方块的数量。

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

EDIT1:第二个版本:这是我一开始和滑块改变时所做的:

// 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 );

            }

【问题讨论】:

  • pixijs.com 怎么样?这是一个 2D 加速框架。我认为 400 万对于今天的计算能力来说是一个非常巨大的数字......
  • 第二个可以显示多少个方块?
  • 只更新已​​更改的内容?如果每秒改变几个方块会有所帮助。对于许多填充矩形,画布会很慢。对于三种方法,您是否每帧都重新创建框?我认为即使有数百万个盒子,webgl 也应该更快。您能否分享更多代码,可以说是您的事件循环?
  • 我不知道这是否会有所帮助,但无论如何它是一本好书:html5rocks.com/en/tutorials/webgl/million_letters
  • 使用一个几何体并在片段着色器中完成所有工作?

标签: javascript html canvas three.js webgl


【解决方案1】:

绘制正方形最快的方法是使用 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 的速度观察 500 万个 3D 点。我相信这也是目前的技术极限。

    我没有自己测试 Potree,所以我不能对这项技术说太多。但是有数据转换器和查看器(基于threejs)所以应该只弄清楚如何转换数据。

    简单介绍一下你的问题

    处理大数据的最佳方法是将它们分组为四叉树 (2d) 或八叉树 (3d)。这将使您不会因距离相机太远或根本不可见的部分而打扰程序。

    另一方面,程序不喜欢你做太多的 webgl 调用。试着像这样理解它,你想要每秒创建大约 60 个图像。但是每次为 GPU 设置一些参数时,程序必须进行一些同步。拆分数据意味着您需要进行更多设置,因此树不能太详细。

    最后,有人说:

    您可能希望将一组值作为着色器制服之一传递

    我不建议这样做,坏主意。纹理查找非常快,但属性总是更快。如果我们谈论的是 4M 点,那么您无法从制服中读取数据。

    对不起,我不能帮你写代码,我可以不用threejs,我不是threejs专家:)

    【讨论】:

      【解决方案3】:

      我会建议尝试 pixi 框架(如上面 cmets 所述)。

      它有 webgl 渲染器,一些基准测试非常有前途。

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

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

      【讨论】:

        猜你喜欢
        • 2015-07-25
        • 1970-01-01
        • 2011-09-23
        • 1970-01-01
        • 1970-01-01
        • 2018-02-14
        • 1970-01-01
        • 2015-09-30
        • 1970-01-01
        相关资源
        最近更新 更多