【发布时间】:2019-02-11 15:32:52
【问题描述】:
简介:
我使用 Three.JS (v95, WebGL Renderer) 渲染等轴测图。该地图包括许多不同的图形图块集。我通过 TextureAtlasLoader 获取特定的图块,它的位置来自 JSON。它看起来像这样:
问题在于,我渲染的图块越多,它的执行速度就越慢(我需要在一张地图上渲染大约 120,000 个图块)。那时我几乎不能移动相机。我知道有几种比将每个图块作为精灵添加到场景中更好的方法。但不知怎的,我被困住了。
当前从代码中提取以创建图块(它在循环中):
var ts_tile = Map.Imagesets[ims].Map.getTexture((bg_left / tw), (bg_top / th));
var material = new THREE.SpriteMaterial({ map: ts_tile, color: 0xffffff, fog: false });
var sprite = new THREE.Sprite(material);
sprite.position.set(pos_left, -top, 0);
sprite.scale.set(tw, th, 1);
scene.add(sprite)
我也尝试过渲染成Mesh,也可以,但是性能是一样的(当然):
var material = new THREE.MeshBasicMaterial({ map: ts_tile, color: 0xffffff, transparent: true, depthWrite: false });
var geo = new THREE.PlaneGeometry(1, 1, 1);
var sprite = new THREE.Mesh(new THREE.BufferGeometry().fromGeometry(geo), material);
网络中可能的解决方案:
我知道我不能在一个场景中添加这么多精灵或网格,我尝试了不同的方法并查看了一些示例,它们完美无缺,但我无法将他们的方法调整到我的代码中。我地图上的每个图块都有不同的纹理并有自己的位置。
官方的three.js 文档中有一个示例:它们使用PointsMaterial 和Points。最后他们只为场景添加了 5 个点,其中包括大约 10000 个“顶点/图像”。文档:https://threejs.org/examples/#webgl_points_sprites
另一种方法可以在 github 上找到:https://github.com/YaleDHLab/pix-plot 他们创建了 5 个网格,每个网格包含大约 4096 个“瓦片”,它们由面、顶点等组成。
最后一个问题:
我的问题是,我怎样才能使我的地图更高效?将我的代码更改为可能的解决方案之一,这让我感到很受挑战。
【问题讨论】:
-
这张地图一定要这样渲染吗?您不能对数据进行预处理并生成 2D 瓦片集(例如 Google 地图),然后显示这些数据的矩阵吗?
-
如果我理解正确:我认为他们在可能的解决方案中对数据进行了预处理并将其渲染为瓦片集(在网格中?)?即使是现在,我也只在 requsetAnimationFrame 中更改相机的位置,而不访问数据。但这就是缓慢的部分出现的地方,因为场景中添加了很多瓷砖。
-
是的,就是这样。您无需渲染许多较小的图块,而是将它们组合/预渲染为更大的图块。它实际上可能是您移动的单个大图像,但当然您最终会得到一个巨大的图像,因此您可以将其拆分为更小的切片。如果缩放是您需要的一项功能,您还需要为每个缩放级别生成不同的图块集。例如,如果您需要渲染“交互式”元素,您可以像现在一样在这些 2D 瓦片上执行此操作。以树为例,如果它们足够稀疏的话。
-
这正是我失败的地方,我不知道如何做到这一点。我可以用一个简单的 2d 画布来实现它(无论如何这太慢了),但我真的很喜欢将 WebGL 的优势与 Three.JS 结合使用。
-
你的问题是你的场景有太多的精灵,每个精灵都有自己的材质。唯一的解决方案是减少精灵的数量。但是您的实现受到精灵材质本身的限制,它们是每个图块的一个图像。我的建议是编写代码,将平铺图像集组合成更大的“预渲染”图像,例如覆盖 10 x 10 平铺,这样你就可以拥有原始精灵数量的 10%。如何生成这些组合的 10 x 10 精灵取决于您,但您不需要即时执行,因此是“预渲染”。
标签: javascript performance three.js