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

WebGL学习笔记(九):阴影的更多相关文章

  1. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  2. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  3. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者http://www.admin10000.com/document/96 ...

  4. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  5. webgl学习笔记五-纹理

    写在前面 建议先阅读下前面我的三篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 webgl学习笔记三-平移旋转缩放 术语 : 纹理 :图像 图形装配区域 :顶点着色器顶点坐标 ...

  6. webgl学习笔记四-动画

    写在前面 建议先阅读下前面我的三篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 webgl学习笔记三-平移旋转缩放   下面我们将讲解下如何让一个正方形动起来~不断擦除和重绘 ...

  7. webgl学习笔记三-平移旋转缩放

    写在前面 建议先阅读下前面我的两篇文章. webgl学习笔记一-绘图单点 webgl学习笔记二-绘图多点 平移 1.关键点说明 顶点着色器需要加上 uniform vec4 u_Translation ...

  8. webgl学习笔记二-绘图多点

    写在前面 建议先看下第一篇webgl学习笔记一-绘图单点 第一篇文章,介绍了如何用webgl绘图一个点.接下来本文介绍的是如何绘制多个点.形成一个面. webgl提供了一种很方便的机制,即缓冲区对象, ...

  9. WebGL学习笔记二——绘制基本图元

    webGL的基本图元点.线.三角形 gl.drawArrays(mode, first,count) first,代表从第几个点开始绘制即顶点的起始位置 count,代表绘制的点的数量. mode,代 ...

  10. go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin)

    目录 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin) zipkin使用demo 数据持久化 go微服务框架kratos学习笔记九(kratos 全链路追踪 zipkin ...

随机推荐

  1. python 读写excel(xls格式)

    import xlrd #导入模块 from xlutils.copy import copy #导入copy模块 rb = xlrd.open_workbook(r"e:\额度导入表.xl ...

  2. Beta冲刺第5次

    二.Scrum部分 1. 各成员情况 翟仕佶 学号201731103226 今日进展 新增将图片转为粉笔画功能代码 存在问题 难者不会,会者不难,主要是参数设置问题 明日安排 视情况而定,可能还是写扩 ...

  3. HDU5036(bitset加速传递闭包+期望)

    HDU5036 题解 题目链接 思路: 求出破坏or打开所有门所需要的期望炮弹数量,那么根据期望的线性性质,我们可以求出每一个门的期望值最后累加起来就行了. 我们最后的目标就是求对于一个门\(i\), ...

  4. Linux学习23-Xftp上传文件显示乱码问题

    前言 当我们在windows新建一个文件,里面有中文时,使用Xftp上传到linux服务器上,会出现乱码问题. Windows的默认编码为GBK Linux的默认编码为UTF-8 Xftp上传文件乱码 ...

  5. js-事件1

    本课我将讲述js中的事件及一些浏览器兼容问题 本章主要从以下几个方面讲起:1.事件流  2.事件的浏览器兼容   3.鼠标,键盘事件 1. 事件流 什么叫事件流? 描述的是事件接受的顺序.这句话听起来 ...

  6. Java Spring Boot 一些调试技巧

    配置文件的管理 有的时候我们希望开发环境和测试环境的配置文件放在一起可以快速切换 spring boot 为我们提供了很方便的的选项 在 application.properties 中只需要添加属性 ...

  7. wordpress调用指定分类除外的置顶文章

    我们有时需要根据实际需要进行一些设置,比如wordpress调用指定分类除外的置顶文章,如何实现呢?随ytkah一起来看看吧,用如下代码插入到需要调取的位置 <div class="r ...

  8. oracle数据库(五)

    PL/SQL基础 PL/SQL语言是对oracle数据库语言的扩展,是一种高性能的基于处理事务的语言,能运行在任何oracle环境中,支持所有数据处理命令,支持所有SQL数据类型和函数,支持所有ora ...

  9. ios Aspects面向切面沉思录—面向结构编程—面向修改记录编程—面向运行时结构编程—元编程?

    1.将主功能看成一个巨大的结构: 2.将切面注入的交叉业务看成是一组结构修改的注册:目标对象+方法是修改的键值: 3.Aspects引擎是修改的执行者.记录者.和维护者: 4.函数和方法是它操作和面对 ...

  10. OpenGL是什么?GPU是什么?

    一.GPU与CPU CPU是处理基本算数运算的单元:它处理的数据是数:整型.浮点型.bool等等: GPU是处理图形运算的单元:它处理的数据是图形的数据矩阵:   GPU的输入是一个和多个图形,输出是 ...