【问题标题】:AFrame: how to use flat shading on a meshAFrame:如何在网格上使用平面着色
【发布时间】:2019-10-11 11:35:45
【问题描述】:

AFrame 性能文档 (https://github.com/aframevr/aframe/blob/master/docs/introduction/best-practices.md) 建议使用预烘焙光照。我已经这样做了,所以现在我希望我的网格使用平面着色。但是我不清楚如何做到这一点?

<a-gltf-model src="..." material="shader: flat">

这没有效果。我还尝试迭代 three.js 中的节点并将每种材料设置为平面,但这也不起作用。尝试一堆东西的完整代码:

<html>
  <head>
    <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
  </head>
  <body>
    <a-scene background="color: #000000">
        <!-- Box.gltf from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Box/glTF -->
        <a-gltf-model id="gltf" src="Box.gltf" position="-1 1 -2"></a-gltf-model>
        <a-box position="1 1 -2" material="shader: flat; color: red"></a-box>
    </a-scene>
    <script>
        var office = document.getElementById( 'gltf' );

        office.addEventListener( 'object3dset', () => {

            const mesh = office.getObject3D( 'mesh' );
            mesh.children[0].material.flatShading = true;
            mesh.children[0].material.needsUpdate = true;
            mesh.children[0].geometry.normalsNeedUpdate = true;

            mesh.traverse( node => {

                if ( node.isMesh === undefined || node.isMesh === false ) {
                    return;
                }

                node.material.flatShading = true;
                node.material.needsUpdate = true;
                node.geometry.normalsNeedUpdate = true;
            } );
        } );
    </script>
  </body>
</html>

呈现如下:

网格(左侧)有阴影,而盒子(右侧)是平面阴影。如何将我的网格设置为使用平面着色?

【问题讨论】:

  • three.js 中的“平面阴影”表示阴影是“分面的”。也许你想要的是“不亮的阴影”。为此使用MeshBasicMaterial;它不响应灯光。
  • 感谢您的评论并为使用不正确的术语道歉。是的,“未点亮的阴影”听起来是对的。你能建议我如何在上面的 AFrame/Three.js 代码中做到这一点吗?
  • 哦,这确实有效!谢谢!将发布答案

标签: three.js aframe


【解决方案1】:

我使用此处的答案来组合一个 a-frame 组件,该组件将 a-entity 设置为未点亮,包括具有子网格的网格

AFRAME.registerComponent('unlit', {

    init: function () {

        function recursivelySetChildrenUnlit(mesh) {

            if (mesh.material && mesh.material.map) {
                mesh.material = new THREE.MeshBasicMaterial({ map: mesh.material.map });
            }

            if (mesh.children) {
                for (var i = 0; i < mesh.children.length; i++) {
                    recursivelySetChildrenUnlit(mesh.children[i]);
                }
            }
        }

        this.el.addEventListener('model-loaded', (e) => {

            const mesh = e.target.getObject3D('mesh');
            for (var i = 0; i < mesh.children.length; i++) {
                recursivelySetChildrenUnlit(mesh.children[i]);
            }

        });
    }
});

你需要做的就是添加 unlit 作为组件,就像这样

<a-entity unlit gltf-model="#model">

【讨论】:

    【解决方案2】:

    OP 错误地将 unlit shading 称为 flat shading。后者通常是对非插值法线着色的引用。我将原始答案保留在下面,因为它仍然对将来的参考有用。


    更新答案

    MeshBasicMaterial 可用于渲染不亮的面。


    原答案

    我不确定是否有办法在 aframe 实例化上修改它,但在 three.js 方面,您可以更新材质着色,如下所示:

    node.material.flatShading = true;
    node.material.needsUpdate = true;
    

    JSFiddle 说明了这一点。

    【讨论】:

    • 感谢您的评论。我更新了答案以尝试您的建议,但仍然没有好处。你可以试试我的 HTML 文件吗?
    • @ScieCode 实际上,您提供的小提琴中不需要normalsNeedUpdate = true。我会避免依赖文档。相反,请进行自己的测试...另外,请注意MeshLambertMaterial 的情况有所不同。它是唯一必须重新计算法线以实现平面着色的材料。
    • 更新答案。
    【解决方案3】:

    根据@WestLangley 的线索,这段代码有效:

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
      </head>
      <body>
        <a-scene background="color: #000000">
            <!-- Box.gltf from https://github.com/KhronosGroup/glTF-Sample-Models/blob/master/2.0/Box/glTF -->
            <a-gltf-model id="gltf" src="Box.gltf" position="-1 1 -2"></a-gltf-model>
            <a-box position="1 1 -2" material="shader: flat; color: red"></a-box>
        </a-scene>
        <script>
            var office = document.getElementById( 'gltf' );
    
            office.addEventListener( 'object3dset', () => {
    
                const mesh = office.getObject3D( 'mesh' );
                mesh.children[0].material = new THREE.MeshBasicMaterial({map: mesh.children[0].material.map});
            } );
        </script>
      </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-21
      • 2019-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多