在计算机视觉中实现三维物体阴影比较出名的一种方案是ShadowMapping,它的基本思路以下:java
第一步:git
1. 建立camera:建立一个位于光源位置的camera,叫作lightCamera。github
2. 建立shadowMap:建立一个有深度纹理的FBO,这个FBO只须要存储深度纹理,不须要颜色缓存区。深度纹理的长宽咱们能够根据不一样的应用场景自定义,不过在大多数状况下都是和viewPort的长宽一致。缓存
3. 渲染场景深度到shadowMap: 将上一步建立的FBO设置为当前的FrameBuffer,而后从lightCamera渲染场景。app
第二步:url
1. 建立camera: 建立一个用于正常场景渲染camera,叫作normalCamera。.net
2. 正常渲染场景:从normalCamera渲染场景,而且把shadowMap传递到fragment shader。orm
3. 顶点转换:顶点坐标在vertext shader须要作两次转换:get
(1): 使用正常渲染场景中的MVP矩阵对顶点作一次转换,而后将新的顶点经过gl_position输出。it
(2): 使用光源位置渲染场景的MVP矩阵对顶点作一次转换,将这个新的顶点命名为lightCoordinate,而后将lightCoordinate经过varying输出。
4. 将lightCoordinate转换为纹理坐标:在fragment shader中lightCoordinate的坐标范围为[-1, 1],可是纹理坐标的范围在[0,1]之间。把lightCoordinate坐标转换为纹理坐标空间须要用一个特别的矩阵乘以lightCoordinate,而后获得新的[x,y,z,w],将x,y视为纹理坐标。这个特别的矩阵以下:
0.5,0.0,0.0,0.0,
0.0,0.5,0.0,0.0,
0.0,0.0,0.5,0.0,
0.0,0.0,0.0,1.0
5. 深度比较:根据上一步获得的纹理坐标从shadowMap中取得深度值shadowZ,把shadowZ和lightCoordinate的Z值作比较,若是shadowZ比较小,就能够认为当前的位置处于阴影中。
以上只是原理介绍,在个人github中有专门的demo实现,地址以下:shadowMapping,有兴趣的同窗能够参考下,但愿对你有所帮助。