• HDRP shader 获取阴影(Custom Pass)


    环境

    Unity:2021.3.0f1
    HDRP:12.1.6
    以下程序均在 自定义全屏通道 中运行,详情

    示例场景如图
    在这里插入图片描述

    直接光阴影

    应该可能是这么写吧(代码出处是Lighting\LightLoop\LightLoop.hlsl

    #pragma multi_compile SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH SHADOW_VERY_HIGH
    
    • 1
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"
    
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/PunctualLightCommon.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl"
    
    • 1
    • 2
    • 3
    • 4
    NormalData normalData;
    DecodeFromNormalBuffer(posInput.positionSS, normalData);
    
    HDShadowContext shadowContext = InitShadowContext();
    
    DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
    float3 L = -light.forward;
    float3 shadow = GetDirectionalShadowAttenuation(shadowContext,
    					posInput.positionSS, posInput.positionWS, normalData.normalWS,
    					light.shadowIndex, L);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    去掉背面的影子

    这个效果不太对劲,不过显然物体背面是接受不到影子的(毕竟照不到光),所以索性去掉背面的阴影。

    shadow = dot(normalData.normalWS, L) < 0 ? 1 : shadow;
    
    • 1

    在这里插入图片描述

    着色

    确实是剩下影子了,不过这样看有点怪怪,所以这里来给这幅图加一个黑白版lambert着色。

    // shadow = dot(normalData.normalWS, L) < 0 ? 1 : shadow;
    shadow *= saturate(dot(normalData.normalWS, L));
    
    • 1
    • 2

    在这里插入图片描述

    所有光源

    为做示例,这里加了一盏聚光灯。
    在这里插入图片描述

    另一个API

    额外添加 #define 和 #include

    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"
    
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/PunctualLightCommon.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl"
    
    // 添加以下内容
    #define LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadowLoop.hlsl"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    如下修改代码(代码出处是Sky\HDRISky\HDRISky.shader

    NormalData normalData;
    DecodeFromNormalBuffer(posInput.positionSS, normalData);
    
    HDShadowContext shadowContext = InitShadowContext();
    
    // 注释以下几行
    // DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
    // float3 L = -light.forward;
    // float3 shadow = GetDirectionalShadowAttenuation(shadowContext,
    //                         posInput.positionSS, posInput.positionWS, normalData.normalWS,
    //                         light.shadowIndex, L);
    // shadow = saturate(dot(normalData.normalWS, L));
    
    float3 shadow3;
    ShadowLoopMin(shadowContext, posInput, normalData.normalWS, 
    		LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA, 
    		DEFAULT_LIGHT_LAYERS, shadow3);
    float3 shadow = dot(shadow3, float3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/2723d58649b54bedab64eb4bb0ef064b.png在这里插入图片描述

    可以看到,聚光灯的影子已经出来了,不过物体背面的影子也出来了,下面继续修改,在这里也来加一个黑白版lambert着色。

    创建 CustomHDShadowLoop.hlsl

    在你上面写的着色器的同目录下新建一个文件,命名为CustomHDShadowLoop.hlsl
    在这里插入图片描述
    HDShadowLoop.hlsl 的所有内容拷贝到 CustomHDShadowLoop.hlsl

    HDShadowLoop.hlsl 的完整路径大概是在:
    “你的项目\Library\PackageCache\com.unity.render-pipelines.high-definition@12.1.6\Runtime\Lighting\LightLoop\HDShadowLoop.hlsl”

    在这里插入图片描述

    修改 CustomHDShadowLoop.hlsl

    1. 在文件最顶上,把 #define SHADOW_LOOP_AVERAGE去除注释
      在这里插入图片描述
    2. 搜索 GetDirectionalShadowAttenuation,并添加代码
    shadowD *= saturate(dot(normalWS, wi));
    
    • 1

    在这里插入图片描述

    1. 搜索 GetPunctualShadowAttenuation,并添加代码
    shadowP *= saturate(dot(normalWS, L));
    
    • 1

    在这里插入图片描述

    1. 最后回去你自己的着色器,修改一下头文件
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/NormalBuffer.hlsl"
        
    #define LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/PunctualLightCommon.hlsl"
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadow.hlsl"
    
    #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoopDef.hlsl"
    // 注释掉这行
    // #include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/HDShadowLoop.hlsl"
    // 改成引用刚刚新建的文件
    #include "CustomHDShadowLoop.hlsl"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    效果就出来了捏
    在这里插入图片描述

    参考

    1. SebLagarde-HDRP getting shadow attenuation-https://forum.unity.com/threads/hdrp-getting-shadow-attenuation.863620/
    2. Material\Lit\Lit.shader 中的 “Forward” Pass(毕竟自定义通道似乎都是向前渲染来着…)

    抛砖引玉,恳请批评指正!

  • 相关阅读:
    HTML5期末考核大作业——学生网页设计作业源码HTML+CSS+JavaScript 中华美德6页面带音乐文化
    基于当量因子法、InVEST、SolVES模型等多技术融合在生态系统服务功能社会价值评估中的应用及论文写作、拓展分析
    ASP.NET Core MVC应用模型的构建[1]: 应用的蓝图
    多线程编程——基础语法篇
    源码安装并运行Haproxy
    ssm+vue+elementUI 高校普法系统-#毕业设计
    计算机竞赛 深度学习人体语义分割在弹幕防遮挡上的实现 - python
    扩容领跑者 Arbitrum 抢占 Layer3 竞争高地
    怎么把pdf合并成一个pdf?认准这几个合并方法
    25 个超棒的 Python 脚本合集
  • 原文地址:https://blog.csdn.net/qq_15505341/article/details/126217597