在unity shader中,通过pass产生阴影,通过主pass的光照 接收阴影!那么问题来了,是先产生阴影吗?还是先接收阴影,执行顺序是啥呢

简单来说,答案是 ShadowCaster Pass 先执行 ,用来生成场景的"深度地图";然后 ForwardBase 等主 Pass 才会去使用这张地图,来计算和绘制阴影效果。

为了帮你更清楚地理解,我们可以把整个过程拆解为两个阶段:

📋 阴影渲染核心流程

阶段 执行Pass 关键任务 产出的数据
第一阶段: 生成阴影映射纹理 ShadowCaster 从光源视角渲染场景,只将深度信息写入一张特殊的"深度图"中 阴影映射纹理 (ShadowMap)
第二阶段: 采样阴影映射纹理 主 Pass (如 ForwardBase/ ForwardLit) 在主相机视角渲染物体时,通过采样第一步生成的 ShadowMap,判断当前片元是否处于阴影中 带阴影效果的最终画面

👣 步骤解析

第一阶段:投射阴影------生成"影子模板"

这个阶段的核心工作,就是为场景创建一个精确的高度地图。ShadowCaster Pass 在其中扮演关键角色:

  1. 阴影映射纹理 (ShadowMap) :此阶段的核心是一张从光源 正交/透视视角渲染的深度纹理。也叫阴影贴图,它不记录颜色,而是记录场景中每个表面到光源的最近距离或深度信息,记录了"哪里照得到光"。

  2. ShadowCaster Pass :每个想要投射 阴影的物体,其 Shader 都必须包含一个 LightMode 标签为 ShadowCaster 的特殊 Pass。若 Shader 本身未定义,Unity 会自动尝试使用 Fallback 中的替代实现。

  3. 渲染调用 :引擎会自动调用场景中所有物体的 ShadowCaster Pass 来渲染并生成阴影映射纹理。

第二阶段:接收阴影------应用"影子模板"

在这个阶段,主摄像机视角下的物体开始渲染,并为最终画面添加阴影。

  1. 比较深度值判断阴影 :场景在主摄像机视角下正常渲染时,Shader 会利用第一阶段生成的 ShadowMap 进行阴影计算。具体来说,对于正在渲染的物体表面上的某点,将其世界坐标转换到光源空间,得到该点"距光源的深度"并与 ShadowMap 中记录的"该方向最近深度"进行比对:若当前深度值大于 ShadowMap 中的值,说明该点被前面物体遮挡了光线,从而判定其在阴影中。

  2. 混合光照结果:采样后得到的阴影值(通常为0到1)会和场景原有的光照、颜色等进行计算,最终输出到屏幕上,形成我们看到的明暗和阴影效果。

🛠️ 代码实现概要

简单来说,阴影的投射与接收依赖在 Shader 中插入特定的代码片段来实现:

  • 投射阴影 :需要包含一个 ShadowCaster Pass。

  • 接收阴影 :需要在主渲染 Pass(例如 ForwardBase)中,利用 Unity 内置的阴影"三剑客"来完成相应功能。

    • SHADOW_COORDS(...):在顶点着色器的输出结构体中定义。

    • TRANSFER_SHADOW(...):在顶点着色器中计算阴影纹理坐标。

    • SHADOW_ATTENUATION(...):在片元着色器采样获取实际阴影值。

💡 一些常见疑问

  1. 前向渲染路径如何处理阴影?

    对于场景中最重要的平行光 ,Unity 会为其生成完整的阴影映射纹理。而点光源或聚光灯的阴影在移动端性能消耗较大,可能需要将渲染路径设为延迟渲染才能开启。

  2. 屏幕空间的阴影映射与普通阴影有何不同?

    这是 Unity 在支持 MRT 的平台上常用的一种优化技术。它的不同之处在于,会利用两张深度图(摄像机深度图和光源 ShadowMap)生成一张屏幕空间的阴影纹理。然后,Shader 通过采样这张纹理来获得阴影,效率更高。

  3. 物体是否需要同时支持投射和接收?

    这两个功能在 MeshRenderer 组件里是分开勾选的,可以自由搭配组合。

💎 总结

通过上面的拆解,应该可以清晰地看到,"阴影投射"指生成数据,"阴影接收"指消费数据,这自然构成"先投射,后接收"的逻辑。

如果还想深入理解 ShadowCaster Pass 的具体写法,或者 SHADOW_ATTENUATION 等内置宏的更多细节,我们可以随时一起进一步探讨。

相关推荐
Behaviour12 小时前
Unity UI循环列表UIScrollViewContent实现
ui·unity·c#·游戏引擎
格林威16 小时前
C#图像快速剪切:使用OpenCvSharp和Halcon优化图像剪切和CPU占用
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机
_ZHOURUI_H_1 天前
Unity EasyECS:并不是所有字段都适合 SoA,Unity 项目中应该怎样拆数据
游戏·unity·性能优化·架构·游戏引擎
亨得利先生1 天前
户外双目3D相机哪家好?SICK Visionary 系列户外选型指南与 Visionary-B Two 分析
数码相机·相机·户外相机·户外3d相机·sick
TO_ZRG1 天前
Unity 编辑器之 SettingsProvider、Hierarchy、Project、SearchField
java·unity·编辑器
yj爆裂鼓手1 天前
spine绑定骨骼运动工具&spine纹理压缩自动设置工具
游戏·unity
惊鸿醉2 天前
Unity 实战:用讯飞 WebAPI 做一个“说普通话、播方言“的语音程序
unity·c#·游戏引擎·语音识别
略略略咯咯2 天前
C#Unity
开发语言·unity·c#
小贺儿开发2 天前
Unity 局域网遥控幻灯片展示工具 1.0
unity·网络通信·工具·ppt·控制·网页·互动
格林威2 天前
C#高位深相机图像保存:12位16位图像保存方案,OpenCvSharp和Halcon实现
开发语言·人工智能·数码相机·计算机视觉·c#·视觉检测·工业相机