????????最近在做Three.js相關(guān)的一些工作,其中需要對(duì)構(gòu)建好的mesh動(dòng)態(tài)改變其著色器,于是就做了下面的修改
this.mesh.material.vertexShader = material.vertexShader;
this.mesh.material.fragmentShader = material.fragmentShader;
????????因?yàn)閙esh是不斷創(chuàng)建、添加到scene中,這就造成了一個(gè)問題,著色器已經(jīng)修改完畢,在場(chǎng)景中應(yīng)該按照修改完的著色器的值來展示,但現(xiàn)實(shí)卻不是,而是一部分按照后來修改的著色器展示,一部分沒有按照修改完的著色器展示,也就是說--修改后的著色器使mesh的展示,一部分正常,一部分異常,這是為什么呢?
????????借助調(diào)試Spector.js工具的先看到修改之前的著色器,這里只看一個(gè)典型值NUMBER_OF_TEXTURES,修改shader之前是4;修改之后依然是4。


????????是不是覺得很怪異,圖片是我偷懶復(fù)制粘貼的,但情況就是這樣,why???
吾日三省吾身,著實(shí)經(jīng)過一番痛苦的自查,自認(rèn)為在代碼賦值這一塊應(yīng)該是沒問題的,那這是什么問題???
后來就仔細(xì)跟了一下Three.js的源碼,發(fā)現(xiàn)在其內(nèi)部使用了一個(gè)叫WeakMap的鍵值對(duì)集合,搜索一下,巴拉巴拉一大堆,核心就最后一段

????????再看一下Three.js是如何使用這個(gè)東西的

在Three.js中這個(gè)類會(huì)將要渲染的material存放在這里面,等下次渲染時(shí)候會(huì)從這個(gè)緩存中查找,如果存在,就直接使用緩存中的shader,恍然大悟,原來如此;



????????上面三幅圖就是造成我修改shader失敗的核心,回過頭再看一下WebGLProperties這個(gè)類,它有一個(gè)remove函數(shù),正好使用就是WeakMap的方法,那就每次修改著色器之前把當(dāng)前的material從鍵值對(duì)中移除就好了吧?

? ? ? ? 那么就把代碼做點(diǎn)修改吧,增加下面一句

? ? ? ? 代碼跑起來,結(jié)果已經(jīng)可以預(yù)見。
????????僅此,記錄一下Three.js的踩坑之旅。