- 0
- 0
- 0
分享
- Unity3D 实用技巧 - Unity Shader 汇总式学习·实战篇 - 阴影
-
原创 2021-04-23
带你快速学习并灵活应用“阴影”,正文开启~
初探阴影的基础原理
官方文档:
基础定义:ShadowMap 技术是从灯光空间用相机渲染一张 RenderTexture,把深度值写入其中所以称之为深度图,在把接受阴影的物体从模型空间转换到灯光空间中,获取深度图里的深度进行比较,如果深度值比深度图中取出的值大就说明该点为阴影。或者也可以理解阴影映射是一个双过程的技术, 场景是以光源的位置为视点被渲染。每个渲染图像的像素的深度被记录在一个“深度纹理”,这个纹理通常被称为阴影贴图。
其实在 Unity3D 编辑器中,Shadow 在 Light 中伴随使用。利用 Shadow Type 属性是否启用阴影 ,结合 Layers 设置可以控制那些层级物体可以接受阴影。具体的详述:
No Shadows:没有阴影。
Hard Shadows:硬阴影,边缘锯齿会比较明显,相对消耗较少资源。
Soft Shadows:软阴影,抗锯齿处理的比较好,阴影柔和真实,但是会消耗较多资源。


实战·基于全透明材质物体上生成阴影
我们知道,按照常规做法,实时阴影直接通过引擎设置,便能达到需要的效果。今天小编与大家一起学习一下,如何在全透明材质的物体上显示阴影。实际应用场景:没有具体的地面,利用一个全透明材质的地面作为承载阴影显示,背景为图片或者全景球。
杂语不多言,直接附上核心代码(基于 URP 渲染管线):
Shader "Custom/ShadowReceiver_Alpha"{SubShader{LOD 200Tags{"RenderType" = "Transparent""RenderPipeline" = "UniversalPipeline""IgnoreProjector" = "True"}Pass{Tags{"LightMode" = "UniversalForward"}Blend SrcAlpha OneMinusSrcAlphaZWrite OnHLSLPROGRAM#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"#pragma prefer_hlslcc gles#pragma exclude_renderers d3d11_9x#pragma target 2.0#pragma vertex HiddenVertex#pragma fragment HiddenFragment// Material Keywords#pragma shader_feature _ALPHATEST_ON#pragma shader_feature _ALPHAPREMULTIPLY_ON// Lightweight Pipeline keywords#pragma multi_compile _ _MAIN_LIGHT_SHADOWS#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS#pragma multi_compile _ _SHADOWS_SOFT// Unity defined keywords#pragma multi_compile _ DIRLIGHTMAP_COMBINED#pragma multi_compile _ LIGHTMAP_ON// GPU Instancing#pragma multi_compile_instancingstruct Attributes{UNITY_VERTEX_INPUT_INSTANCE_IDfloat4 positionOS : POSITION;};struct Varyings{float4 positionCS : SV_POSITION;float4 shadowCoord : TEXCOORD0;};Varyings HiddenVertex(Attributes input){Varyings output = (Varyings)0;UNITY_SETUP_INSTANCE_ID(input);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);output.shadowCoord = GetShadowCoord(vertexInput);output.positionCS = vertexInput.positionCS;return output;}half4 HiddenFragment(Varyings input) : SV_Target{UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);half s = MainLightRealtimeShadow(input.shadowCoord);int addLightCount = GetAdditionalLightsCount();for (int i=0;i<addLightCount;i++){//s += AdditionalLightRealtimeShadow(i,input.shadowCoord);}return half4(0, 0, 0, 1 - s);}ENDHLSL}UsePass "Universal Render Pipeline/Lit/DepthOnly"}FallBack "Hidden/InternalErrorShader"}
然后,地面属于透明材质,注意设置 Render Queue 为 3000。效果如下:

另外也汇总一下灯光阴影在使用上限制:
01 在各个平台中,看不到实时阴影的情况时,可以在 Edit>Project Setting>Quality 中将 Shadow Distance 的数值调高就能看到实时的投影了。
02 方向光源在 Forward 模式下才可以启用阴影,点光源和聚光灯的阴影,如果想要开启的话需要在 PlayerSetting 把渲染模式改为 Deferred Lighting 即可。
03
VertexLit:顶点光照,光照效果最一般的,不支持阴影,一般用于配置较差的移动设备;
Forward:正向着色,能够很好的支持光照效果,不支持点光源和聚光灯的阴影,一般采用烘焙的方式来处理更多的阴影;
Deferred Lighting:延迟光照,支持最佳的光照效果以及所有类型的光照投影,但是需要硬件支持。
04 使用阴影级联属性:使用级联阴影有很好的阴影质量,特别是远距离观看,级联阴影通过分割可视区域住部分变大,并使用相同大小的阴影贴图,所以实际上利用阴影级联属性牺牲一部分性能我们将获得近处更好的阴影分辨率。
相关资源推荐
[1] Unity 的实时阴影 - ShadowMap 实现原理:
[2] Unity 产生阴影的几种方式详解:
[3] Unity 移动端动态阴影总结:
[4] 半透明物体如何实现阴影效果?
https://blog.uwa4d.com/archives/TechSharing_123.html
[5] 如何实现更真实的软阴影效果
基于 Unity 的光线追踪(一)
https://www.bilibili.com/read/cv7803119/
基于 Unity 的光线追踪(二)
https://www.bilibili.com/read/cv7827098/
基于 Unity 的光线追踪(三)





长按关注
第一时间了解Unity引擎动向,学习最新开发技巧

点击“阅读原文”,可跳转社区阅读哦
-
阅读原文
* 文章为作者独立观点,不代表数艺网立场转载须知
- 本文内容由数艺网收录采集自微信公众号Unity官方平台 ,并经数艺网进行了排版优化。转载此文章请在文章开头和结尾标注“作者”、“来源:数艺网” 并附上本页链接: 如您不希望被数艺网所收录,感觉到侵犯到了您的权益,请及时告知数艺网,我们表示诚挚的歉意,并及时处理或删除。





