3D中实现实时阴影技术中比较常见的方式是阴影映射(Shadow Mapping),我们这里也以这种技术来实现实时阴影。

阴影映射背后的思路非常简单:我们先以光的位置为视角进行渲染,我们能看到的东西都将被点亮,看不见的一定是在阴影之中了(这里会将是否可视的信息作为深度贴图进行渲染)。假设有一个地板,在光源和它之间有一个大盒子。由于光源处向光线方向看去,可以看到这个盒子,但看不到地板的一部分,这部分就应该在阴影中了。

平行光的阴影实现方式

相对来说,平行光的实现要简单得多,下面我们看看平行光的阴影实现原理:

  1. 创建一个帧缓冲对象,用来渲染深度贴图;
  2. 创建一个和光源方向一致的摄像机对象;
  3. 创建接收深度的贴图对象;
  4. 通过自己编写的着色器,渲染深度信息到贴图中;
  5. 渲染模型时,将之前渲染好的阴影深度贴图传入,通过计算出每个像素相对于平行光的深度之后,和阴影深度贴图上的可显示深度进行对比,如果是不可显示的像素,则当前像素值乘于阴影颜色即可;

示例请查看:https://hammerc.github.io/dou3d-ts/learning/learningNotes/lesson_10/Shadow.html

马赫带

片段着色器中判断当前像素是否处于阴影之中的代码如下:

float visibility = (shadowCoord.z > depth) ? 0.7 : 1.0;

这么写的话,会出现一条一条的纹路,被称为马赫带,解决办法是给深度加上 0.005 的分量,如下:

float visibility = (shadowCoord.z > depth + 0.005) ? 0.7 : 1.0;

阴影生成时使用的透视矩阵类型

一般来说模拟平行光时,生成阴影贴图使用可以使用正交相机,当然也可以使用透视相机来实现距离越近阴影越大的效果;

点光源,点光源不同于平行光,是向所有方向发射光源,所以不能简单的使用平行光的方法来实现,主要的区别在于平行光使用了一个平面贴图,而点光源需要使用一个立方体贴图来实现,具体可以参考:https://blog.csdn.net/jxw167/article/details/57477261

提高精度

上面我们实现了阴影,不过有一个问题,当我们把光照的位置拉远之后(仅使用透视矩阵生成阴影贴图时),会发现阴影消失了:

var LIGHT_X = 0, LIGHT_Y = 40, LIGHT_Z = 2;

这是因为,我们把 gl_FragCoord.z 的深度值存储在只有 8 位的红色分量中导致的,所以距离过远之后,8 位的红色分量就存储不下了,好的方法是所有的分量都用上来存储;

修改后的示例如下:https://hammerc.github.io/dou3d-ts/learning/learningNotes/lesson_10/Shadow_highp.html

阴影投影到球体

除了可以投影到平面,阴影也可以投影到任意模型上,比如球体:https://hammerc.github.io/dou3d-ts/learning/learningNotes/lesson_10/Shadow_highp_sphere.html

最新文章

  1. Dependency Injection in ASP.NET Core
  2. Vim 常见操作
  3. Create XO Checker Game With Oracle Forms
  4. Netsharp快速入门(之6) 基础档案(创建导航菜单)
  5. 高效使用Bitmaps(一) 大Bitmap的加载
  6. 3D旋转特效
  7. 【 D3.js 入门系列 — 1 】 第一个程序 HelloWorld
  8. X86寄存器全称
  9. linux和android开发链接
  10. Java-ServletConfig
  11. Hive 查询元数据库获取某个分区的count数
  12. PEB标记反调试方法
  13. Es5中的类和静态方法 继承
  14. MySQL复制框架
  15. 01_re正则表达式
  16. noip2007-4
  17. python第十七课——列表生成式
  18. rancher下的kubernetes之二:安装rancher和kubernetes
  19. 机器学习基石第三讲:types of learning
  20. hdu 2141:Can you find it?(数据结构,二分查找)

热门文章

  1. 轻量级C#编辑器RoslynPad((基于Roslyn编译器))
  2. 没有rc.local的解决办法
  3. Pytorch之Dataparallel源码解析
  4. Linux libcurl安装及注意事项
  5. Elasticsearch 概念理解
  6. python+ddt+unittest+excel+request实现接口自动化
  7. 转载 Easyui Tree方法扩展 - getLevel(获取节点级别)
  8. 异常sql处理
  9. LeetCode 702. Search in a Sorted Array of Unknown Size
  10. linux学习10 Linux目录结构和根文件系统全面讲解