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. Vue-cli3 中 通过在index.html添加的script js文件 如何在组件内使用不会 xxx is not defined错误

    以jQuery 为例 第一种方法 更改webpack配置信息 1.在vue.config.js中(如果没有 请在根目录新建)配置如下信息 // const webpack = require('web ...

  2. win黑窗口命令

    rd 删除 文件夹, 语法: rd [/S] [/Q] [drive:]path 参数: drive 盘符 path 文件路径 /S   递归删除文件夹( 删除前, 要确认是否进行删除) /Q  关闭 ...

  3. 内核中dump_stack的实现原理(1) —— 栈回溯

    环境 Aarch64 Qemu aarch64-linux-gnu-gcc linux-4.14   概述     栈回溯的目的是将函数的调用栈打印出来,对于分析函数调用和debug系统异常会很有帮助 ...

  4. Kali linux network is unreachable

    使用树莓派4 安装完kali linux后,配置好ip,能ping通上级路由. 但ping公网地址显示网络不可达. Ping: connect: network is unreachable 解决方法 ...

  5. SQL基础篇(MICK)

    SQL基础教程(Mick) 数据库和SQL C:\PostgreSQL\9.5\bin\psql.exe -U postgres -d shop 数据库的基本概念 数据库(DB):将大量数据保存起来, ...

  6. Unity 渲染教程(五):多个光源

    https://www.jianshu.com/p/c1a9a5d27765 对每个物体渲染多个光源的光照效果. 支持不同的光源类型. 使用光源cookie. 计算顶点光照. 在光照计算中添加球面谐波 ...

  7. 2019年杭电多校第二场 1002题Beauty Of Unimodal Sequence(LIS+单调栈)

    题目链接 传送门 思路 首先我们对\(a\)正反各跑一边\(LIS\),记录每个位置在前一半的\(LIS\)中应该放的位置\(ans1[i]\),后一半的位置\(ans2[i]\). 对于字典序最小的 ...

  8. 201671030106 何启芝 实验十四 团队项目评审&课程学习总结

    项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十四 团队项目评审&课程学习总结 课程学习目 ...

  9. JSR303/JSR-349,hibernate validation,spring validation 之间的关系

    JSR303是一项标准,JSR-349是其的升级版本,添加了一些新特性,他们规定一些校验规范即校验注解,如@Null,@NotNull,@Pattern,他们位于javax.validation.co ...

  10. mcp2515屏蔽寄存器和过滤寄存器的学习

    mcp2515是can控制器,简单的来讲,就是只要配置好寄存器,芯片就能够自动的解析can数据帧,同时保存到接收缓存中,提醒单片机可以读取can的数据字节. 读取的方式是快速spi,可以达到10Mbi ...