(一)渲染路径
1 前向渲染
ForwardBase ,
可实现,光照纹理、环境光、自发光、阴影。(环境光、自发光希望值计算一次)
ForwardAdd,
默认不支持阴影,但可以加编译指令开启。
每个光源执行一次pass
通常开启混合模式,免得覆盖颜色。看起来只受一个光源影响一样
原理:
1,如果满足深度测试,往下
2,进行光照计算
3,更新帧缓冲
- UnityShader 通常定义一个Base以及一个Add,add根据光源数量进行多次调用。Base用于环境光、自发光、第一重要像素光(平行光),第二个pass(add),计算其他光源。没有可以不要这个pass的吧
总结,N*M个pass (N物体,M光源)
2顶点照明渲染路径
3延迟渲染路径
原理:
pass1:计算G缓冲
pass2:
a,如果可见往下
b, 读取缓冲信息,更新
优点:
1,当光源数量多到,用前向渲染会有瓶颈。可使用。
2,每个光源都可逐像素处理。
缺点:
1,不支持真正的抗锯齿
2,不能处理半透明物体
3,显卡要求
(二)阴影
1.原理
- 相机和光源重合,相机能看到的表面,形成的记录距离相机最近表面位置的深度图--叫做,阴影纹理(shadowMap)。
- 传统的,用base和add更新深度信息,但是,此处需求是深度信息而已,掺杂了光的计算了,所以,unity 用特殊pass,LightMode-shadowcaster 来
- 传统的,在光源空间比较深度。 unity在屏幕空间比较深度。(屏幕空间的阴影映射技术-ScreenSpace Shadow Map)(延迟渲染)
【以下重点重复看】主要的步骤如下:
1.首先得到从当前摄像机处观察到的深度纹理。在延迟渲染里这张深度图本来就有,如果是前向渲染的话就需要把场景整个渲染一遍,把深度渲染到深度图中。
2.然后再从光源出发得到从该光源处观察到的深度纹理,也被称为这个光源的ShadowMap。
3.然后在屏幕空间做一次阴影收集计算(Shadows Collector),这次计算会得到一张屏幕空间阴影纹理,也就是说这张图里面需要有阴影的部分已经显示在图上了。这个过程概括来说就是把每一个像素根据它在摄像机深度纹理中的深度值得到世界空间坐标,再把它的坐标从世界空间转换到光源空间中,和光源的ShadowMap里面的深度值对比,如果大于ShadowMap中的深度距离,那么就说明光源无法照到,在阴影内。
4.最后,在正常渲染物体为它计算阴影的时候,只需要按照当前处理的fragment在屏幕空间中的位置对步骤3得到的屏幕空间阴影图采样就可以了。
西山居程序YOung的自定义实现
- 对于普通的shader虽然看不到LightMode-shadowcaster,其实在 FallBack "Specular"(注释掉,ta就不能产生阴影了。)
2.shader阴影 BassPass全家桶!
//阴影0 - pragma
#pragma multi_compile_fwdbase //为得到正确的光照变量,如光照衰减值等
//阴影1 - include
#include "AutoLight.cginc"
//阴影2 - v2f
SHADOW_COORDS(2)
//阴影3 - vert
TRANSFER_SHADOW(o);
//阴影4 - frag
fixed shadow = SHADOW_ATTENUATION(i);
注意: 如果LightModel 没有ShadowCaster,FallBack内部也没有对应的ShadowCaster,那么该shader,将不会对相机深度图和ShadowMap产生影响。(不能投影到别的物体)
透明物体的阴影
fallback Transpaerent/Cuttoff/VetexLit
_Cuttoff
- ,#include "AutoLight.cginc", 下面要的宏在此声明
- SHADOW_COORDS(.)
- 1 用于对阴影纹理采样的坐标。
- 2 在顶点着色器计算上一步中声明的阴影纹理坐标
- 3 片元着色器计算阴影值。
透明测试的阴影:
fallback 要用 Transparent/Cutout/VertexLit
要声明_Cutoff 因为上面这个兄弟用到了
-注意命名写死(TRANSFER_SHADOW 用到了。)
a2v里vertex,
v2f里pos,v
(三)扩展
1.UWA 移动端动态阴影
Unity移动端动态阴影总结
1 基于Cubemap的动态软阴影
2 地面云阴影
3 植物摇曳阴影
4 结合Projector和Rendertexture的实时阴影
5 角色脚下阴影面片
6 Light Probe
7 Shadow Maps