【问题标题】:How can I merge geometries in A-Frame without losing material information?如何在 A-Frame 中合并几何而不丢失材料信息?
【发布时间】:2021-02-19 21:57:43
【问题描述】:

我有大量使用自定义几何图形的块对象,我希望将它们合并到数量较少的较大几何图形中,因为我相信这会降低渲染成本。

我一直在遵循这里的指导:https://aframe.io/docs/1.2.0/introduction/best-practices.html#performance,这使我在这里找到了几何合并组件: https://github.com/supermedium/superframe/tree/master/components/geometry-merger/

A-Frame 文档说: “您可以使用几何合并,然后使用启用顶点颜色的 three.js 材质。three.js 几何保留颜色、每个顶点的 uvs 等数据。”

几何合并组件还说: “如果使用顶点或面着色作为单个几何图形的颜色仍然可以单独操作,则很有用,因为该组件保留了一个 faceIndex 和 vertexIndex。”

但是我有几个问题。

  1. 如果我在材质上设置 vertexColors(按照 A-Frame 文档的建议),那么这会破坏我的块的外观。
  2. 无论我是否在我的材质上设置了 vertexColors,当几何图形合并时,所有材质信息似乎都丢失了,一切都以白色结束。

查看此故障以演示这两个问题。 https://tundra-mercurial-garden.glitch.me/

我怀疑 A-Frame geometry-merger 组件无法满足我的需要,我需要使用底层的 three.js 函数自己实现一些东西。

是这样吗,或者有没有一种方法可以使用几何合并来完成这项工作?

【问题讨论】:

    标签: aframe


    【解决方案1】:

    要使vertexColors 工作,您需要为顶点着色:)
    更具体地说 - BufferGeometry 期望每个顶点都有一个 rgb 值数组 - 这将用作材质的颜色。


    在这段代码中:
    var geometry = new THREE.BoxGeometry();
    var mat = new THREE.MeshStandardMaterial({color: 0xffffff, vertexColors: THREE.FaceColors});
    var mesh = new THREE.Mesh(geometry, mat);
    

    除非几何图形包含有关顶点颜色的信息,否则网格将为黑色:

    // create a color attribute in the geometry
    geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(vertices_count), 3));
    // grab the array
    const colors = this.geometry.attributes.color.array;
    
    // fill the array with rgb values
    const faceColor = new THREE.Color(color_hex);
    for (var i = 0; i < vertices_count / 3; i += 3) {
       colors[i + 0] = faceColor.r; // lol +0
       colors[i + 1] = faceColor.g;
       colors[i + 2] = faceColor.b;
    }
    // tell the geometry to update the color attribute
    geometry.attributes.color.needsUpdate = true;
    

    由于某种原因,我无法使 buffer-geometry-merger 组件工作,但它的核心似乎是有效的:

    AFRAME.registerComponent("merger", {
      init: function() {
        // replace with an event where all child entities are ready
        setTimeout(this.mergeChildren.bind(this), 500);
      },
      mergeChildren: function() {
       const geometries = [];
       // traverse the child and store all geometries.
       this.el.object3D.traverse(node => {
         if (node.type === "Mesh") {
           const geometry = node.geometry.clone();
           geometry.applyMatrix4(node.parent.matrix);
           geometries.push(geometry)
    
           // dispose the merged meshes 
           node.parent.remove(node);
           node.geometry.dispose();
           node.material.dispose();
         }
       }); 
       // create a mesh from the "merged" geometry         
       const mergedGeo = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
       const mergedMaterial = new THREE.MeshStandardMaterial({color: 0xffffff, roughness: 0.3, vertexColors: THREE.FaceColors});
        
       const mergedMesh = new THREE.Mesh(mergedGeo, mergedMaterial);
       this.el.object3D.add(mergedMesh)
     }
    })
    

    您可以在this glitch 中查看。还有一个使用顶点颜色的例子here (source)。

    【讨论】:

    • afaik 实例化也需要几何图形中的颜色属性,如果您想要不同的颜色。
    • 我最初的着色方法(应用于几何体上配置的组的材质)似乎与实例化网格配合得很好。例如。 slow-guttural-cemetery.glitch.me 另见:github.com/diarmidmackenzie/instanced-mesh
    • @DiarmidMackenzie 如果我错了,请纠正我,但看起来你有三个相同立方体但材料不同的池 - 我在评论中的意思是创建一个能够拥有的单个实例化网格其实例的不同颜色
    • 好的理解。我的意思是在每个网格中,我有 2 种不同的颜色:黑色框架和面部颜色。这使我可以将绘制调用从 2N = (其中 N 是块数)降低到 2K (其中 K 是颜色数)。这足以满足我的需求。在您的故障混音中,您的调用次数甚至更低,但转向顶点着色似乎失去了黑框?
    • @DiarmidMackenzie 我会尝试做一个可靠的例子,但说起来容易做起来难,而且需要一段时间(我确实有一个关于实例化网格的想法,但对于合并我需要测试一下位)。
    【解决方案2】:

    我同意听起来您需要考虑其他解决方案。以下是使用 A-Frame 进行实例化的两个不同实例:

    两者都不是完美的,甚至都不是完全完成的,但希望可以让您作为指南开始。

    【讨论】:

      【解决方案3】:

      虽然我最初的问题是关于几何合并,但我现在认为在这种情况下,Instanced Meshes 是一个更好的解决方案。

      基于this suggestion,我实现了这个新的 A-Frame 组件: https://github.com/diarmidmackenzie/instanced-mesh

      此故障显示了使用此组件仅通过 19 次调用即可渲染原始故障的场景。如果每个对象都单独渲染,则需要超过 200 次调用。 https://dull-stump-psychology.glitch.me/

      一个关键的限制是我无法为所有不同的块颜色使用一个网格,但必须为每种颜色使用一个网格(总共 7 个网格)。

      InstancedMesh 可以支持不同颜色的元素,但每个元素必须有一个颜色,而这个场景中的元素每个有 2 种颜色(黑框 + 脸色)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-29
        • 1970-01-01
        相关资源
        最近更新 更多