本文是视频课程《Unity技术美术TA:Shader篇》,算是对自己学习的总结,也希望分享下所学知识~~
阴影的作用:
1.可以增加真实度
2.可以提升空间感
阴影如何产生的?
光线被阻挡的结果
实时阴影实现方式
ShadowMapping:常用的试试阴影生成方法
ShadowMap:动态生成阴影纹理,需要时进行对其采样
实现原理:
1.在光源处添加一个相机,开启深度测试与写入,生成ShadowMap(深度图)
2.绘制场景时,把当前片段转换到光源空间下,计算得到深度与采样ShadowMap中的深度值对比
测试流程:
深度图Pass
阴影如何投射?
使用系统的方法需要开启unity设置
十分简单,都是unity封装好的
Pass //ShadowCaster需要一个单独的pass
{
Tags
{
//设置为 shadowcaster pass
"LightMode" = "ShadowCaster"
}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"‘
struct appdata
{
float4 vertex: POSITION;
half3 normal :NORMAL;
};
struct v2f
{
//加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据.
V2F_SHADOW_CASTER;
};
v2f vert(appdata v)
{
v2f o;
//主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象.
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//处理阴影
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
阴影如何接收?
Unity 需要开启 Shadow Receive
//Pass内设置为 前向渲染,否则渲染顺序不对,可能一会显示一会不显示
Tags
{
"LightMode" = "ForwardBase"
}
//添加宏定义,使用内置函数
#pragma multi_compile_fwdbase
//添加引用
#include "AutoLight.cginc"
// ...
//顶点到片断着色器参数修改
struct v2f
{
// SV_POSITION 一定要其名为 pos 内置函数
float4 pos : SV_POSITION;
...
//unity会声明一个叫_ShadowCoord的float4变量,用作阴影的采样坐标.
SHADOW_COORDS(1)
};
v2f vert(appdata v)
{
v2f o;
...
//将上面定义的_ShadowCoord纹理采样坐标变换到相应的屏幕空间纹理坐标,为采样阴影纹理使用.
TRANSFER_SHADOW(o)
return o;
}
fixed4 frag(v2f i) : SV_Target
{
...
//atten即存储了采样后的阴影.
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos)
return finalCol * atten;
}
注意:
必须有ShadowCaster Pass 才可以已正常的显示阴影
阴影分级效果(LOD)
Shader里面可以通过 LOD 控制某个 SubShader 是否执行
SubShader
{
LOD 100
...
}
SubShader
{
LOD 50
...
}
这样如果 ShaderLOD 大于100就会直接执行第一个不执行第二个
如果在 50-100之间就会执行第二个
如果小于 50 就什么也没有
(注意:跟顺序也有关系,从上到下找的)
同时在Csharp代码里设置
Shader.globalMaximumLOD = XXX;