当前位置: 首页 > article >正文

Unity URP支持多光源阴影

前文:Unity URPShader支持多光源处理

上文只是简单的实现了光照照亮效果,但是并没有实现多光源的阴影投射功能,接下来就是对此功能的整合。

接收阴影

//声明需要的变体和文件
//平行光的阴影
#pragma shader_feature _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
//额外光的阴影
#pragma shader_feature _ _ADDITIONAL_LIGHT_SHADOWS
//阴影质量选择
#pragma shader_feature _ _SHADOWS_SOFT _SHADOWS_SOFT_LOW _SHADOWS_SOFT_MEDIUM _SHADOWS_SOFT_HIGH

#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
//shadowCoord 代表主光源平行光采样ShadowMap的阴影UV,shadowMask是额外光的遮罩
#if _RECEIVESHADOW_ON
        float4 shadowCoord = TransformWorldToShadowCoord(positionWS);
        o.shadowCoord = shadowCoord;
        #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
            half4 shadowMask = inputData.shadowMask;
        #elif !defined(LIGHTMAP_ON)
            half4 shadowMask = unity_ProbesOcclusion;
        #else
            half4 shadowMask = half4(1, 1, 1, 1);
        #endif
#endif
//顶点处理
  #ifdef _ADDITIONAL_LIGHTS_VERTEX
      uint pixelLightCount = GetAdditionalLightsCount();
      #if _RECEIVESHADOW_ON
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, positionWS, shadowMask);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
          }
      #else
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, positionWS);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, o.normalWS);
          }
      #endif

额外光处理的主要函数是GetAdditionalLight(),可以在RealtimeLights hlsl文件中找到几个重载方法。

//片元处理
  //光照
  half3 lightColor = i.lightColor;
  #if _RECEIVESHADOW_ON
      Light main_light = GetMainLight(i.shadowCoord);
      half3 main_light_dir = normalize(main_light.direction);
      half diffuse_term = dot(normalize(i.normalWS), main_light_dir) * 0.5 + 0.5;
      lightColor += diffuse_term * main_light.color * (main_light.shadowAttenuation + 0.5);
      #ifdef _ADDITIONAL_LIGHTS
          uint pixelLightCount = GetAdditionalLightsCount();
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz, i.shadowMask);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
          }
      #endif
  #else
      Light main_light = GetMainLight();
      half3 main_light_dir = normalize(main_light.direction);
      half diffuse_term = dot(normalize(i.normalWS), main_light_dir) * 0.5 + 0.5;
      lightColor += diffuse_term * main_light.color;
      #ifdef _ADDITIONAL_LIGHTS
          uint pixelLightCount = GetAdditionalLightsCount();
          for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
          {
              Light light = GetAdditionalLight(lightIndex, i.positionWS.xyz);
              half3 attenuatedLightColor = light.color * (light.distanceAttenuation * (light.shadowAttenuation + 0.5));
              lightColor += LightingLambert(attenuatedLightColor, light.direction, i.normalWS);
          }
      #endif
  #endif

投射阴影

  Pass
  {
      Name "ShadowCaster"
      Tags { "LightMode" = "ShadowCaster" }

      ZWrite On
      ZTest LEqual
      ColorMask 0
      Cull[_Cull]

      HLSLPROGRAM
      
      #pragma vertex vert
      #pragma fragment frag
      #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
      #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
      struct Attributes
      {
          float4 positionOS : POSITION;
          float3 normalOS : NORMAL;
      };

      struct Varyings
      {
          float4 positionHS : SV_POSITION;
      };

      half3 _LightDirection;

      Varyings vert(Attributes v)
      {
          Varyings o;
          float3 positionWS = TransformObjectToWorld(v.positionOS.xyz);
          float3 normalWS = TransformObjectToWorldNormal(v.normalOS.xyz);

          positionWS = ApplyShadowBias(positionWS, normalWS, _LightDirection);
          o.positionHS = TransformWorldToHClip(positionWS);

          #if UNITY_REVERSED_Z
              o.positionHS.z = min(o.positionHS.z, UNITY_NEAR_CLIP_VALUE);
          #else
              o.positionHS.z = max(o.positionHS.z, UNITY_NEAR_CLIP_VALUE);
          #endif

          return o;
      }
      half4 frag(Varyings i) : SV_TARGET
      {
          return 0;
      }

      ENDHLSL
  }


http://www.kler.cn/news/288577.html

相关文章:

  • 解决windterm莫名其妙输入ctrl+c的问题
  • 【IC设计】跨时钟异步处理系列——单比特跨时钟
  • 时间序列的解密者:循环神经网络在时间序列分析中的应用
  • 【docker】docker 是什么
  • 为啥一定要考HCIE安全?这4个理由你不得不看
  • Docker 镜像构建
  • 持续集成与持续部署(CI/CD)的深入探讨
  • 铭江酒趣乐园小程序
  • HarmonyOS开发实战( Beta5版)跨线程序列化耗时点分析工具使用规范指南
  • 计算机基础知识+CSP真题册
  • weblogic漏洞——CVE-2020-14882
  • “京东云深海数据平台” 焕新升级
  • 艾体宝洞察丨透过语义缓存,实现更快、更智能的LLM应用程序
  • 计算二叉树的深度(LeetCode)
  • 旗帜分田(华为od机考题)
  • 用ChatGPT提升论文质量:改进语法、用词和行文的有效方法
  • WinForm技巧之自定义条件
  • 1688精选货源API接口升级||1688选品
  • 数学基础 -- 线性代数之行阶梯形
  • JavaScript高级进阶(一)
  • SprinBoot+Vue停车场管理微信小程序的设计与实现
  • C# 上位机开发指南:高效学习建议
  • 力扣刷题--LCP17.速算机器人【简单】
  • ChatGPT 3.5/4新手使用手册(附:案例)
  • LabVIEW电机多次调用
  • 基于RAG多层次的多代理架构来处理时序任务
  • Vue3中 defineProps 与 defineEmits 基本使用
  • hive中datediff函数介绍
  • 二百五十九、Java——采集Kafka数据,解析成一条条数据,写入另一Kafka中(一般JSON)
  • verilog 中的for循环用法