【Unity Shader】Unity中阴影走样的解决方案
走样问题出现在两个地方:
- 初始采样:获得shadowmap的过程
- 重采样:从摄像机视角对Shadowmap进行重采样
这两个阶段都会产生走样问题。
1 初始采样-透视走样
1.1 形成原因
这里的情况其实跟纹理类似,是由于近景大量pixel与shadowmap中的同一个texel对应导致的走样。详细一点的解释如下图:
从光源位置采样获得shadowmap时,此时摄像机并没有进行透视投影,shadowmap在世界空间是均匀分配的。如上左图所示:橙色箭头位置对应的三个texel都对应着世界空间下相同大小的pixel,此时的pixel数量分配还保持着近平面小所以少,远平面大所以多。
由于世界空间变换到屏幕空间需要经过透视投影,透视投影后原本大小不一样的近平面和远平面在屏幕内所占pixel变得一样了,但是前面获取的shadowmap和视锥体内物体的对应关系并没有改变,这导致了什么?——对于近平面/前景,shadowmap的一个texel将对应屏幕里的很多pixel,因此就会出现下述情况:
虽然远处的A和近处的B明明分辨率是一样的,但图中靠近摄像机B的阴影就出现了明显的块状感,也就是透视走样。
1.2 解决方案-CSM
其实有两种解决办法,第一种就是在光源位置采样获得shadowmap之前,我们先做一次透视投影,那就不会出现透视投影之后一个texel对应的pixel远、近平面不一样的情况了。
第二种解决办法,级联阴影映射(Cascaded Shadow Map),它也是目前公认的透视走样最有效的解决思路。
CSM的想法思路
采取某种办法尽量减少近平面和远平面之间的像素差距,像素差距小了,那透视对texel覆盖关系的影响不就少了!
CSM的具体办法
从它的解决办法看,级联阴影映射又可以叫做多重阴影映射,因为说白了就是一种采用多张shadowmap去实现阴影的技术。具体操作:通过平行于视图方向的切片将视锥体截成多个子视锥体,每一个子视锥体都对应一张shadowmap,每张shadowmap独立计算但分辨率相同,如下图:
对于级联的划分,一般采用对数划分,具体划分我直接截图了(图来自7.2 Shadow Map
还需知道的是:如果真的在view space也就是视锥体划分级联,一旦镜头转动会产生很严重的闪烁,所以一般划分级联是在光源空间中划分。(参考DX12渲染管线(6) - 级联阴影与距离场阴影中的说法)
1.3 Unity中的CSM
Unity可以在Project setting里可以进行级联阴影分级的设置:
- Shadow Cacades
Unity提供2和4两种划分方案,一般来讲4已经足够了。
- Cascade splits
图里选择的是Four Cascades,底下0-4咋占比越来越大?结合下图来看,每张shadowmap的分辨率是相同的,但是离摄像机越近的子视锥体它的质量应该越高,越远的质量越低,相同分辨率的条件下当然是越精细/小,细节刻画的就越细致。所以0-3是按照近->远分的,这样划分还可以充分利用资源。
- Shadow Distance
用来控制近平面到级联阴影的最远距离,整个级联阴影也是只在这个范围内产生阴影,这也减少了阴影带来的开销。
查看shadowmap绘制过程
在Unity里随便搭一个阴影相对较多的场景,在Frame Debug里查看shadowmap的整个绘制过程,会发现它就是按照4张分别进行的,如下图:
2 重采样走样
关于这个其实就是Games202作业1的内容了,我在GAMES202作业1-实现过程详细步骤中也详细说明了PCF和PCSS是如何实现的,展示了过程,这里我不再赘述~
Unity中的阴影类型
用户是可以通过选择Light组建的Shadow Type来选择阴影的Hard/Soft。
至于Unity中具体是如何实现的,打算去学校图书馆借来《Unity 3D 内建着色器源码剖析》那本书看看,后期肯定对管线搭建的学习有所帮助,这里就不再说了。
最后我只想说,阴影这里只学到PCF和PCSS是远远不够的。因为Unity已经给我们把关键的东西都写好了,内置着色器往往帮了一个大忙。网上也有很多大佬抛弃Unity自己搭建一个阴影系统, 例如实时渲染-阴影渲染实现(Unity)等等,后期我也会尝试srp管线的搭建,那时一定会重新捡起来阴影这部分继续深入学习。
【Unity Shader】Unity中阴影走样的解决方案相关推荐
- 2d shader unity 阴影_【Unity Shader】平面阴影(Planar Shadow)
来介绍一种适用于移动平台的高性能实时阴影解决方案--平面阴影(Planar Shadow). 由于Unity内置的实时阴影实现方式是屏幕空间阴影贴图(Screen Space Shadow Map)非 ...
- 关于Unity 3D 运行中崩溃的案例解决方案
Unity3D生成日志的路径是: C:\User\Administrator\Local Settings\Application Data\Unity\Editor 找到Editor.log 下面是 ...
- Unity Shader 麻将平面阴影高光
做了一个麻将高光和阴影的材质,第一个shader,纪念一下~直接贴代码 // 高光在第一个pass,阴影在第二个pass // Upgrade NOTE: replaced '_Object2Worl ...
- unity shader实现中枪散红效果,(参考别人算法)
法向量的确很神奇 !! Shader "Custom/RedBound2" { Properties { _MainTex ("Base (RGB ...
- Unity Shader:Unity网格(1)---顶点,三角形朝向,法线,uv,以及双面渲染三角形
1,顶点 顶点是网格最基础的组成部分,可通过mesh.vertices获取和赋值.mesh.vertices是一个Vector3的数组,每个Vector3代表了此顶点在世界空间中的位置每个Vector ...
- Unity Shader unity文档学习笔记(十七):径向模糊 实现类似冲锋时的速度感
实现思路:离中心点越远的像素 模糊效果越明显 UV偏移的量越大 shader // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'Uni ...
- Unity Shader unity文档学习笔记(十一):战争迷雾核心算法
核心算法 非常简单 主要就是把一个点的世界坐标转换到贴图的UV坐标 给整个场景一个大的plane 加上写的shader 摄像机位置调成plane的正上方 Shader "Unlit/FogR ...
- Unity Shader - 放大镜
前言 今天闲来无事,实现了一个简单的放大镜特效. 效果图如下: 思路 思路其实很简单,大致分为两个步骤: 先实现整体放大效果: 最后在一定范围内放大(这里是圆) 既然是放大镜,那也就是对图像的处理, ...
- Unity Shader - 模仿RenderImage制作全屏Quad,可以制作自定义后处理的流程
文章目录 先尝试GL类来制作 Shader CSharp 画个三角型 画个全屏的Quad 发现GL没有RenderTarget之类的 使用CommandBuffer来绘制全屏的Quad GL渲染到目标 ...
最新文章
- 使用Gradle构建Monorepo项目
- 登录时本地保存账号密码及关闭ARC的方法
- BASE64Encoder及BASE64Decoder的正确用法
- 2017.07.16小组赛题目I
- 淘宝商品类目查询方法怎样查看别人商品的类目淘宝类目查询工具软件
- 计算机论文物业管理系统,小区物业管理系统的设计与实现(计算机毕业设计)...
- python差分进化算法_差分进化算法(differential evolution)的Python实现
- 宋宝华——Linux设备驱动开发详解:基于最新的Linux 4.0内核(第一章)
- CAD打印adobe acrobat pro/DC 安装的PDF打印机闪退问题
- mysql 数据库内存不足_MySQL数据库内存不足怎么办 MySQL数据库使用教程
- 谷歌李开复 我的传奇人生源于十句箴言
- 注销的计算机管理员如何恢复,十分钟后如何注销用户?Power Manager是这样做的!...
- File “C:\Users\hjl\AppData\Local\Programs\Python\Python38\lib\site-packages\pymysql\err.py“, line 1
- C#之DES加密解密
- 前端技巧培训-后台战友快速入门
- uint8array和string的互转(包括中文字符串)
- LC99 Recover Binary Search Tree
- 单片机定时报警C语言程序,求一个51单片机定时闹钟程序。要C语言。能够调时间...
- what is Mono?
- uniGUI之UniButton