这里不是说图形学理论,也不是说URP这个分支的区别(另外2个分支:built-in,HDRP),最终还是想说说自定义编程管线(自定义变成相当于,实现一整个渲染引擎),之后会说,但现在也不是说自定义编程的时候
其实下面说的还是HLSL编程,Shader代码(只不过披了一个URP模板的皮)
目录
Unity 的 ShadowMask原理
很多刚接触图形学渲染Renderer,特别是入门工具是Unity的同学,
很容易混淆各种Shadow概念;
第一眼看到这样的代码:Pass{ “ShadowCaster",就先入为主认为这是渲染Shadow的代码
投影的最基本原理就是
1.光源
2.遮挡者(投射源)
3.阴影绘制(Object Render)
其实ShadowCaster Pass,就是是投射源(主要是告诉引擎,如何定位,阴影的粒度,是否要偏移,然后引擎在某些时段就会烘培对应阴影贴图);而阴影的绘制和颜色的绘制没差,其实都在ForwardPass(或者DefferPass, 这个下个文章会说到)
void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData)
{
//。。。。。。。。。。。
inputData.shadowMask = SAMPLE_SHADOWMASK(input.lightmapUV);
因为上面的代码,我们知道,.shadowMask存放在inputData
所以,
half4 UniversalFragmentPBR(InputData inputData, SurfaceData surfaceData)
{
//。。。。。。。
// To ensure backward compatibility we have to avoid using shadowMask input, as it is not present in older shaders
#if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
half4 shadowMask = inputData.shadowMask;
#elif !defined (LIGHTMAP_ON)
half4 shadowMask = unity_ProbesOcclusion;
#else
half4 shadowMask = half4(1, 1, 1, 1);
#endif
Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask);
又由这段代码,我们知道了shadowMask其实是混在了主光(平行光)一同计算的,其实光==1,阴影==0,光++,阴影--;也不是那么难以理解的事情
但是,点光源就不需要阴影了吗?
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, inputData.positionWS, shadowMask);
由于这段代码,我们也知道了,点光源的阴影和平行光的阴影是一样的
//平行光(其他工具类似的名字:Main Lit,主光源,直接光源)
light.shadowAttenuation = MainLightShadow(shadowCoord, positionWS, shadowMask, _MainLightOcclusionProbes);
//点光源,聚光灯 (其他工具类似的名字:Other Lit,辅助光,间接光源)
light.shadowAttenuation = AdditionalLightShadow(perObjectLightIndex, positionWS, shadowMask, occlusionProbeChannels);
再看一段代码:
#ifdef CALCULATE_BAKED_SHADOWS
half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
#else
half bakedShadow = 1.0h;
#endif
所以我们知道了 shadowMask只再Baked模式下起作用,也顺带了解了要给关键字:occlusionProbeChannels
各种名字,概念傻傻分不清楚
<具体分析,之后再补上>
结论还是上一个文章的结论:
尽信书不如无书
其实没那么多深奥的道理
掌握了天下的理论(实际上不可能全部掌握),还不如一句代码
实战Shader阴影”魔改“。。。。??
1.无阴影
根据上一个文章的代码(实现了点光源和聚光灯),一个阴影 ??
一开始以为,是这个问题
后来发现,还是代码(官方)作怪
#if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
return 1.0h;
#endif
<因为被官方坑了很多次,所以不怎么会浪费时间,直接看代码就好了,都能从代码中找到解决方法>
2.有阴影
// 官方建议的打开宏写法,_ADDITIONAL_LIGHT_SHADOWS_CASCADE不知道什么作用
//#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
//#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
//#define _ADDITIONAL_LIGHT_SHADOWS_CASCADE
//#define _ADDITIONAL_LIGHT_SHADOWS;
//目测,_ADDITIONAL_LIGHT_SHADOWS开了,就会把ADDITIONAL_LIGHT_CALCULATE_SHADOWS打开
//所以光是 ADDITIONAL_LIGHT_CALCULATE_SHADOWS 也就可以了,_ADDITIONAL_LIGHT_SHADOWS_CASCADE暂时作用不明
#define ADDITIONAL_LIGHT_CALCULATE_SHADOWS 0;
//测试宏是否有打开,需要某付费IDE支持
#if !defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
abc = 1 //ADDITIONAL_LIGHT_CALCULATE_SHADOWS已定义,所以即使这行错误不完整的代码,也不会报错
#endif
//Light light = GetAdditionalLight(lightIndex, positionWS);
float4 shadowMask = SAMPLE_SHADOWMASK(i.uv.zw);//lightmapUV
Light light = GetAdditionalLight(lightIndex,positionWS,shadowMask);
//现在这个light结构体就会带着阴影信息
3.阴影又没有了
我们改一下,没有了(我们要的?)
4.诶,又有了
<最后,你还是发现人物的影音并没有>
这里,有无阴影的区别在于:是否有勾选静态物件,是否MeshRenderer
然而SkinnedMeshRenderer并没有这个选项,《Unity2020》
参考
Unity实时阴影实现——Shadow Mapping - 知乎
Shadowmask vs DistanceShadowmask - Unity Forum
如何在unity的URP下实现阴影_黄琅的博客-CSDN博客_unity urp 阴影