material 中对 normalMap 的引用返回未定义

reference to normalMap in material returning undefined

我正在尝试制作一个简单的演示,使用 dat.GUI 来操作 Aframe 基元上的 material。在实体标签上,我创建了一个 material,并为普通插槽分配了一个纹理。

<a-entity id="circle" geometry="primitive:circle; radius: 2; segments: 96" 
rotation="-90 0 0"
            material="color: #335500; transparent: true; opacity: 0.9; 
normalMap: #watertex; side: double"
            water ></a-entity>

然后,在一个自定义组件中,我访问了它的三个网格和 material。 我能够获得对 material 的引用,但是当我尝试访问 normalMap 时,它 returns 未定义。

我添加了一个侦听器,等待 "loaded" 事件。我没有使用 gltf,所以 "model-loaded" 是不必要的。 我使用了 getObject3D("mesh"),并遍历了网格,但法线贴图仍然 returns 未定义。令人费解的是,在控制台中,我记录了material,并且可以清楚地看到normalMap。但是当记录它时,它 returns undefined.

    AFRAME.registerComponent("water",{
        init: function(){
            let el = this.el;
            //console.log(el);
            let comp = this;
            this.counter=0;

            el.addEventListener("loaded", function(ev){
                console.log('model loaded');
                let mesh = el.getObject3D('mesh');
                if (!mesh){return;}
                mesh.traverse(function(node){
                    if (node.isMesh){
                        console.log(node);
                        console.log(node.material);
                        console.log(node.material.normalMap); <-- returns 
                                                                 undefined
                    }
                });  
            });
        },          
    });

<a-entity id="circle" geometry="primitive:circle; radius: 2; segments: 96" 
rotation="-90 0 0"
            material="color: #335500; transparent: true; opacity: 0.9; 
normalMap: #watertex; side: double"
            water ></a-entity>

我很惊讶对 material 的引用显示法线贴图 console.log(node.material);

但直接引用法线贴图失败 console.log(node.material.normalMap);

我怀疑用 aframe 制作的纹理贴图可能有些奇怪,无法从 Threejs 访问,但我不知道为什么或如何测试这个。

最终我想使用 datGUI 来控制 material 中的参数。 我注意到 AFrame material 组件没有公开 threejs materials 的所有参数。此外,使用 datGUI 访问一些 aframe material 参数似乎有点问题。所以这就是我想直接访问threejs的原因。

这是我服务器上项目的 link,您可以在其中看到控制台日志。 http://sensorium.love/experiments/demos/water/waterDemo1.html

如果你想玩代码,这里有一个小故障 https://glitch.com/~water-demo

这似乎是一场比赛,您试图在 normalMap 应用之前访问它。


有一个 materialtextureloaded 事件 (docs) 似乎可以解决问题:

el.addEventListener('materialtextureloaded', e => {
    // nomalMap is accessible here
})


否则,您还可以使用超时或间隔来确定 normalMap 何时不为空。

我见过 ar.js 做:

let timer = setInterval(e => {
      if (!someVal) return;

      clearInterval(timer);
      // here someVal isn't null or undefined
}, 500)

故障 here.


我很确定您可以在控制台中看到 normalMap,因为一旦您在浏览器控制台中单击箭头,就会对表达式求值。在 chrome 上有一个蓝色的 "i",上面写着 "value below was evaluated just now"。