Version: 6000.3
语言: 中文
内置渲染管线中的环境光着色器示例
在内置渲染管线中接收阴影着色器示例

内置渲染管线中的阴影投射着色器示例

一个像猫一样的角色漂浮在飞机上空,并在飞机上投下阴影。
一个像猫一样的角色漂浮在飞机上空,并在飞机上投下阴影。

我们着色器在 GPU 上运行的程序。更多信息
请参阅术语表
目前既不能接收阴影,也不能投射阴影。我们先实现阴影投射。

为了投射阴影,着色器必须在其任何子着色器或任何回退中具有 ShadowCaster 通道类型。ShadowCaster 通道用于将对象渲染到阴影贴图中,通常它相当简单 -顶点着色器 渲染模型时在 3D 模型的每个顶点上运行的程序。更多信息
请参阅术语表
只需要评估顶点位置,片段着色器几乎不做任何事情。阴影贴图只是深度缓冲区保存图像中每个像素的 z 值深度的内存存储,其中 z 值是投影平面中每个呈现像素的深度。更多信息
请参阅术语表
,因此即使是片段着色器输出的颜色也无关紧要。

这意味着对于许多着色器,阴影投射器通道将几乎完全相同(除非对象具有基于自定义顶点着色器的变形,或者具有 alpha 切口/半透明部分)。拉入它的最简单方法是通过 UsePass 着色器命令:

Pass
{
    // regular lighting pass
}
// pull in shadow caster from VertexLit built-in shader
UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"

然而,我们在这里学习的是,所以让我们可以这么说地“手动”做同样的事情。对于较短的代码,我们已将光照通道(“ForwardBase”)替换为仅执行无纹理环境的代码。在它下面,有一个“ShadowCaster”通道,使对象支持阴影投射。

Shader "Lit/Shadow Casting"
{
    SubShader
    {
        // very simple lighting pass, that only does non-textured ambient
        Pass
        {
            Tags {"LightMode"="ForwardBase"}
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            struct v2f
            {
                fixed4 diff : COLOR0;
                float4 vertex : SV_POSITION;
            };
            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                half3 worldNormal = UnityObjectToWorldNormal(v.normal);
                // only evaluate ambient
                o.diff.rgb = ShadeSH9(half4(worldNormal,1));
                o.diff.a = 1;
                return o;
            }
            fixed4 frag (v2f i) : SV_Target
            {
                return i.diff;
            }
            ENDHLSL
        }

        // shadow caster rendering pass, implemented manually
        // using macros from UnityCG.cginc
        Pass
        {
            Tags {"LightMode"="ShadowCaster"}

            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_shadowcaster
            #include "UnityCG.cginc"

            struct v2f { 
                V2F_SHADOW_CASTER;
            };

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

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

现在下面有一个平面,使用常规的内置漫反射着色器,这样我们就可以看到我们的阴影正在工作(请记住,我们当前的着色器还不支持接收阴影!

我们使用了 #pragma multi_compile_shadowcaster 指令。这会导致着色器被编译成多个变体,并为每个变体定义了不同的预处理器宏(有关详细信息,请参阅多个着色器变体页面)。渲染到阴影贴图中时,点光源与其他光源类型的情况需要略有不同的着色器代码,这就是需要此指令的原因。

内置渲染管线中的环境光着色器示例
在内置渲染管线中接收阴影着色器示例