楔子
相信很多人都知道,通過ShadowMap可以產生陰影,通過渲染陰影可以增加場景渲染的對比度,增加渲染的真實效果。 如下圖所示:
但是對於透明或者半透明的物件,WebGL在處理陰影效果的時候,會把他當成一個不透明的物件來處理,這也渲染的陰影效果就顯得很假。 比如下面樹得陰影效果:
真實物理得效果中,樹可能會有一些透光得間歇,所以陰影一般都不是一整塊得效果。而是有些透光得亮點,如下圖所示:
場景中,多家一些樹,這種對比會更加明細,如下面兩幅圖所示,前面一個是整片陰影,後面一個是有半透陰影得效果:
半透陰影效果原來
實現半透陰影,可以通過透明度測試(alphaTest)功能來實現。一般來說,一張半透明得圖片中,一部分地方是很透明得,opacity接近與零,我們希望在opacity小於某個值得時候,不生成陰影,可以通過alphaTest,把小於閾值得片元在生成陰影貼圖的時候丟棄掉,自然就不會生成陰影。 所以流程大致如此:
- 繪製陰影貼圖的時候,生成一個深度材質,設定深度材質alpahTest(=[閾值])和map,map是原本材質的貼圖。 如果原本材質有alphaMap,也需要考慮在深度材質上面加上alphaMap。
- 正常繪製場景流程。
threejs 實踐
通過three 實踐,首先在材質上面增加要給屬性shadowAlphaTest,通過shadowAlphaTest動態指定繪製陰影時候的alphaTest,如下所示:
this.shadowAlphaTest = undefined;
在生成深度材質的地方,如下修改:
result.alphaTest = material.shadowAlphaTest || material.alphaTest;
result.map = material.map;
result.alphaMap = material.alphaMap;
然後再繪製的時候,可以動態修改shadowAlphaTest的值,來達到控制半透陰影的效果,如下所示:
child.material.transparent = true;
child.material.opacity = 1.0;
child.material.shadowAlphaTest = 0.5;
最終的效果如下所示:
結語
如果有疑問,關注公號“ITMan彪叔” 可以新增作者微信進行交流,及時收到更多有價值的文章。