阴影LightMode = ShadowCaster

本文深入探讨Unity中的阴影技术实现原理,包括使用ShadowMap技术、前向渲染路径中的阴影映射纹理计算方法,以及如何在Shader中采样阴影映射纹理以实现物体间的阴影交互。此外,还介绍了透明物体阴影处理技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

阴影

实现原理

  使用Shadow Map技术。把摄像机与光源位置重合,光源的阴影部分就是摄像机看不到的地方。

  前向渲染路径中,最重要的平行光如果开启了阴影,Unity就会为光源计算阴影映射纹理(shadowmap),本质就是深度图,记录光源出发到最近表面位置。两种方法: 
1. 摄像机放在光源位置,然后按正常渲染流程(调用Base Pass 和 Additional Pass)来更新深度信息,得到阴影映射纹理。 
2. 摄像机放在光源位置,调用额外的Pass:LightMode = ShadowCaster,把顶点变换到光源空间,渲染目标不是帧缓存,而是阴影映射纹理。

阴影采样

  • 传统方法: 
    • 正常渲染Pass,计算顶点的光源空间,用xy分量对纹理采样,如果顶点值大于该深度值,就说明在阴影区域。
  • Unity5及以后: 
    • 屏幕空间的阴影映射技术(Screenapce Shadow Map)。是在延迟渲染中产生阴影的方法。不过需要显卡支持MRT。根据阴影映射纹理和深度纹理得到屏幕空间的阴影图。阴影图包含了屏幕空间所有阴影区域。

接收其他物体阴影

  在Shader中对阴影映射纹理(包括屏幕空间的阴影图)进行采样,结果和最后的光照相乘即可。

向其他物体投射阴影

  把物体加入到光源的阴影映射纹理计算中(让其他物体可以得到该物体信息),即执行LightMode 为 ShadowCaster的Pass。


具体实现

使用AutoLight.cginc文件内的三个宏: 
- SHADOW_COORDS:声明了一个名为_ShadowCoord的阴影纹理坐标变量。 
- TRANSFER_SHADOW:根据不同平台实现。如果使用了屏幕空间的阴影映射技术,会使用内置ComputeScreenPos函数计算_ShadowCoord;否则就直接把顶点转换到光源空间存到_ShadowCoord。 
- SHADOW_ATTENUATION:对_ShadowCoord采样,得到阴影信息。

需要注意:内置宏用了一些变量名需要在自己定义的时候要匹配:a2f的顶点坐标为vertex,输出的v2f结构体名为v,v2f中顶点位置名为pos。

  1. 计算阴影深度,绘制深度纹理: 
  2. 绘制阴影: 
  3. 最后图形: 

BasePass:

...

#include "AutoLight.cginc"          // 计算阴影的宏

...

struct v2f {
    ...
    // 对阴影纹理采样的坐标,参数为下一个可用插值寄存器的索引值(前面TEXCOORD0和1,所以这里是2)
    SHADOW_COORDS(2)
};

v2f vert(a2v v) {
    ... 
    // 计算阴影纹理坐标
    TRANSFER_SHADOW(o); 
    return o;
}

fixed4 frag(v2f i) : SV_Target {
    ...
    // 计算阴影值
    fixed shadow = SHADOW_ATTENUATION(i);
    return fixed4(ambient + (diffuse + specular) * atten * shadow, 1.0);
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

衰减和阴影统一管理

  使用AutoLight.cginc的内置宏UNITY_LIGHT_ATTENUATION,不再需要自己判断光源类型等,也不用在BasePass中单独处理阴影。如果Additional Pass需要添加阴影,用#pragma multi_compile_fwdadd_fullshadows命令。 
  第一个参数变量名,宏会创建这个名字的变量;第二个参数为v2f结构体,用来计算阴影;第三个参数是世界空间的坐标,计算光照衰减。

fixed4 frag(v2f i) : SV_Target {
    ... // 不需要定义atten,下面宏会自己定义

    // 使用内置宏同时计算光照衰减和阴影。自动声明atten变量。
    UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

    return fixed4(ambient + (diffuse + specular) * atten, 1.0);
}

 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

部分源码如下。可以看到点光源、聚光灯、平行光的计算。后面还有部分代码是根据是否启用cookie的情况做不同版本的宏。 


透明物体的阴影

透明测试与阴影

如果直接使用FallBack默认回调(VertexLit、Diffuse、Specular),往往无法得到正确的阴影,因为在透明测试中某些片元丢弃了,而默认回调没有进行这样的处理。可以使用回调Transparent/Cutout/VertexLit。可见源文件Alpha-VertexLit.shader。

第一个:FallBack “Transparent/VertexLit”;第二个:FallBack “Transparent/Cutout/VertexLit”;第三个:基于第二个同时在MeshRenderer的Cast Shadows选择Two Sided。 

透明混合与阴影

由于需要关闭深度写入,阴影处理变得复杂,所以内置半透明的Shader都是没有阴影效果的。可以修改Fallback为VertexLit、Diffuse等不透明物体用的UnityShader。

默认不投射不接收阴影(FallBack “Transparent/VertexLit”): 

强制接收阴影(FallBack “VertexLit”),但不能透过立方体看到后面墙壁的阴影: 


半透明阴影

原文见这里。 
实现原理:对物体剔除一些片元(挖洞),通过洞的密度和大小,伪造出阴影的透明效果,实际阴影颜色没有改变。_DitherMaskLOD就是用来计算哪些地方挖洞的纹理。 
关键代码:tex3D(_DitherMaskLOD, float3(vpos.xy_0.25,alpha_0.9375)).a

<think>好的,用户的问题是关于在Gazebo中为caster_link设置材料,特别是Gazebo/Black的正确用法和示例。我需要先回忆Gazebo中材质配置的相关知识。通常,在Gazebo中,材质可以通过URDF或SDF文件中的visual标签来设置。材质名称可能以Gazebo/为前缀,比如Gazebo/Black。 首先,用户提到引用[1]中的示例命令是启动rrbot,可能相关的配置文件里有caster_link的设置。可能需要检查该机器人的URDF文件,看其中是否有关于caster_link的visual部分,是否有material标签。 然后,正确的做法是在URDF的link部分,为caster_link的visual元素指定material。例如,在visual标签下添加<material name="Gazebo/Black"/>。需要确认Gazebo是否支持这种命名方式,或者是否需要使用其他格式,比如颜色值或不同的命名空间。 另外,用户可能需要示例代码。应该给出一个具体的URDF片段,展示如何为caster_link设置材质。同时,提醒用户注意可能的大小写敏感问题,比如Gazebo和Black的首字母是否大写,或者是否需要使用下划线等。 可能还需要提到,在Gazebo中,除了使用预设的材质名称,还可以自定义颜色,使用<ambient>, <diffuse>, <specular>等属性来设置RGBA值。但用户明确提到Gazebo/Black,所以重点应放在使用预设材质上。 需要检查是否有常见的错误,比如拼写错误,或者是否遗漏了Gazebo命名空间。例如,是否正确使用name属性,是否在material标签内正确闭合等。 总结步骤应该是:1. 在URDF文件中找到caster_link的visual部分;2. 添加material标签,指定name为Gazebo/Black;3. 保存并启动Gazebo查看效果。可能还需要提醒用户,如果材质没有生效,可以尝试重新加载模型或检查Gazebo的日志信息。 此外,用户可能需要知道如何验证材质是否应用成功,比如在Gazebo的GUI中查看模型外观,或者使用Gazebo的材料属性工具检查。 最后,生成相关问题,比如如何自定义颜色,如何解决材质不显示的问题,或者如何在不同链接中重用材质定义。</think>在Gazebo中为`caster_link`设置材质`Gazebo/Black`,需通过URDF/SDF文件的`<visual>`标签定义。以下是具体步骤和示例: 1. **在URDF文件中定位`caster_link`** 找到该link的`<visual>`标签,添加`<material>`子标签: ```xml <link name="caster_link"> <visual> <geometry><!-- 几何形状定义 --></geometry> <material name="Gazebo/Black"/> <!-- 关键配置 --> </visual> <!-- 其他标签(碰撞/惯性) --> </link> ``` 2. **材质命名规则** - 使用前缀`Gazebo/`调用内置材质,如`Gazebo/Black`、`Gazebo/Red`等[^1] - 需注意大小写敏感,例如`Gazebo/Black`与`gazebo/black`可能不同 3. **验证效果** 启动模型后,在Gazebo界面中检查该link的颜色是否变为黑色。若未生效,可通过`gz model -m <model_name> -p`命令重新加载模型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值