在Three.js中动态改变meterial的着色器的不起作用的问题

        最近在做Three.js相关的一些工作,其中需要对构建好的mesh动态改变其着色器,于是就做了下面的修改

this.mesh.material.vertexShader = material.vertexShader;

this.mesh.material.fragmentShader = material.fragmentShader;

        因为mesh是不断创建、添加到scene中,这就造成了一个问题,着色器已经修改完毕,在场景中应该按照修改完的着色器的值来展示,但现实却不是,而是一部分按照后来修改的着色器展示,一部分没有按照修改完的着色器展示,也就是说--修改后的着色器使mesh的展示,一部分正常,一部分异常,这是为什么呢?

        借助调试Spector.js工具的先看到修改之前的着色器,这里只看一个典型值NUMBER_OF_TEXTURES,修改shader之前是4;修改之后依然是4。


shader修改之前


shader修改之后

        是不是觉得很怪异,图片是我偷懒复制粘贴的,但情况就是这样,why???

吾日三省吾身,着实经过一番痛苦的自查,自认为在代码赋值这一块应该是没问题的,那这是什么问题???

后来就仔细跟了一下Three.js的源码,发现在其内部使用了一个叫WeakMap的键值对集合,搜索一下,巴拉巴拉一大堆,核心就最后一段


Why WeakMap


        再看一下Three.js是如何使用这个东西的

WebGLProperties


在Three.js中这个类会将要渲染的material存放在这里面,等下次渲染时候会从这个缓存中查找,如果存在,就直接使用缓存中的shader,恍然大悟,原来如此;


修改后的shader
缓存中的shader


最后返回的shder

        上面三幅图就是造成我修改shader失败的核心,回过头再看一下WebGLProperties这个类,它有一个remove函数,正好使用就是WeakMap的方法,那就每次修改着色器之前把当前的material从键值对中移除就好了吧?

WeakMap的remove方法

        那么就把代码做点修改吧,增加下面一句

修改后的赋值方式

        代码跑起来,结果已经可以预见。

        仅此,记录一下Three.js的踩坑之旅。

你可能感兴趣的:(在Three.js中动态改变meterial的着色器的不起作用的问题)