《Unity Shader入门精要》自学笔记(八)第九章 更复杂的光照 —— Unity的阴影

产生阴影的原理:光沿直线传播
即,从光源出发,看不到的地方都处于阴影中

Unity处理阴影的两种途径

传统的阴影映射

  1. 调用LightMode为ShadowCaster的Pass,获取光源的阴影映射纹理ShadowMap(包含可以被光源照亮的点的z值)
  2. 正常渲染的Pass中,将顶点转换到光源空间中,获取该顶点在光源空间中的xy坐标,以及深度值z
  3. 使用顶点在光源空间中的xy坐标,对ShadowMap进行采样获得深度值Z
  4. 若z > Z,则该点处于阴影中

屏幕空间的阴影映射(Screenspace Shadow Map)

原本为延迟渲染中的方法,需要显卡支持MRT,否则使用传统的阴影映射处理

  1. 调用LightMode为ShadowCaster的Pass,获取光源的阴影映射纹理ShadowMap(可以被光源照亮的点的z值),和摄像机的深度纹理DepthMap(可以显示在屏幕上的点的z值)
  2. 使用ShadowMap和DepthMap计算获得屏幕空间的阴影图(显示在屏幕上的每一个像素是否可以被光源照亮的信息)

阴影的投射与接收

在这里插入图片描述

阴影的投射

若想让一个物体投射阴影给其他物体,需要将该物体添加到光源的阴影映射纹理ShadowMap的计算中(即shader中应包含LightMode为ShadowCaster的Pass,如果没有就会去FallBack中查找),否则该物体无法投射阴影

在Unity中,需要在Inspector中MeshRender组件的Lighting-CastShadows属性进行设置

注意:一些特殊情况下可能需要将CastShadows设置为“Two Sided”,因为默认情况下在计算光源阴影映射纹理时会剔除掉网格的背面,导致无法生成阴影

阴影的接收

若想让一个物体接收阴影,需要在着色时对光源的阴影映射纹理ShadowMap进行采样,并对光照结果进行相乘处理

在Unity中,需要勾选Inspector中MeshRender组件的Lighting-ReceiveShadows选项

ShadowCaster Pass

功能:将深度信息写入渲染目标中
渲染目标:光源的阴影映射纹理,或摄像机的深度纹理
所在内置着色器:VertexLit
使用:一般情况下不需要自己写,而是直接FallBack到含有该Pass的内置着色器
具体内容(提取于Unity内置着色器:builtin_shaders-2019.4.21f1.zip\DefaultResourcesExtra\Normal-VertexLit.Shader),大概了解一下:

// Pass to render object as a shadow caster
Pass {
   
    Name "ShadowCaster"
    Tags {
    "LightMode" = "ShadowCaster" }

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag
    #pragma target 2.0
    #pragma multi_compile_shadowcaster
    // allow instanced shadow pass for most of the shaders
    #pragma multi_compile_instancing 
    
    #include "UnityCG.cginc"

    struct v2f {
   
        V2F_SHADOW_CASTER;
        UNITY_VERTEX_OUTPUT_STEREO
    };

    v2f vert( appdata_base v )
    {
   
        v2f o;
        UNITY_SETUP_INSTANCE_ID(v);
        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
        TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
        return o;
    }

    float4 frag( v2f i ) : SV_Target
    {
   
        SHADOW_CASTER_FRAGMENT(i)
    }
    ENDCG
}

其中appdata_base为内置结构体,包含顶点位置、顶点法线、第一组纹理坐标

阴影接收相关的内置宏

阴影计算“三剑客”

SHADOW_COORDS
作用:声明一个用于对阴影纹理采样的坐标

struct v2f {
   
    // *为了宏正确执行,与SV_POSITION绑定的变量名必须为pos
	float4 pos : SV_POSITION; 
	float3 worldNormal : TEXCOORD0;
	float3 worldPos : TEXCOORD1;
	// TEXCOORD0、TEXCOORD1已被使用,下一个可用的纹理坐标为TEXCOORD2
	SHADOW_COORDS(2)
};

TRANSFER_SHADOW
作用:计算阴影纹理坐标

struct a2v {
   
	// * 为了宏正确执行,顶点坐标必须命名为vertex
	float4 vertex : POSITION;
	float3 normal : N
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值