wedge
I believe many people know that shadows can be generated through ShadowMap. By rendering shadows, the contrast of scene rendering can be increased and the real effect of rendering can be increased. As shown below:
But for transparent or translucent objects, when WebGL processes the shadow effect, it will treat it as an opaque object, which also renders the shadow effect very fake. For example, the following tree has a shadow effect:
In the real physical effect, the tree may have some intermittent light transmission, so the shadow is generally not a monolithic effect. Instead, there are some bright spots that are transparent, as shown in the following figure:
In the scene, there are many trees, the contrast will be more detailed, as shown in the following two pictures, the front one is the whole shadow, and the latter one has the effect of semi-transparent shadow:
Semi-transparent shadow effect original
To achieve semi-transparent shadow, it can be achieved through the transparency test (alphaTest) function. Generally speaking, in a semi-transparent image, some parts are very transparent, and the opacity is close to zero. We hope that when the opacity is less than a certain value, no shadow will be generated. We can use alphaTest to generate fragments smaller than the threshold value. When discarding the shadow map, naturally no shadow will be generated. So the process is roughly like this:
- When drawing the shadow map, generate a depth material, set the depth material alpahTest (=[threshold]) and map, map is the texture of the original material. If the original material has alphaMap, you also need to consider adding alphaMap to the depth material.
- Draw the scene flow as normal.
threejs practice
Through the practice of three, first add the attribute shadowAlphaTest to the material, and dynamically specify the alphaTest when drawing the shadow through shadowAlphaTest, as shown below:
this.shadowAlphaTest = undefined;
In the place where the depth material is generated, modify it as follows:
result.alphaTest = material.shadowAlphaTest || material.alphaTest;
result.map = material.map;
result.alphaMap = material.alphaMap;
Then when drawing, you can dynamically modify the value of shadowAlphaTest to achieve the effect of controlling semi-transparent shadows, as shown below:
child.material.transparent = true;
child.material.opacity = 1.0;
child.material.shadowAlphaTest = 0.5;
The final effect looks like this:
Epilogue
If you have any questions, follow the public account "ITMan Biao Shu", you can add the author's WeChat to communicate, and receive more valuable articles in time.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。