soft shadow mask

This commit is contained in:
StarBeats 2025-07-17 17:21:42 +08:00
parent ec312c498e
commit 9852662f7d
13 changed files with 429 additions and 189 deletions

View File

@ -38,7 +38,7 @@ MonoBehaviour:
m_MainLightRenderingMode: 1 m_MainLightRenderingMode: 1
m_MainLightShadowsSupported: 1 m_MainLightShadowsSupported: 1
m_MainLightShadowmapResolution: 2048 m_MainLightShadowmapResolution: 2048
m_AdditionalLightsRenderingMode: 1 m_AdditionalLightsRenderingMode: 2
m_AdditionalLightsPerObjectLimit: 4 m_AdditionalLightsPerObjectLimit: 4
m_AdditionalLightShadowsSupported: 1 m_AdditionalLightShadowsSupported: 1
m_AdditionalLightsShadowmapResolution: 2048 m_AdditionalLightsShadowmapResolution: 2048

View File

@ -347,7 +347,7 @@ MonoBehaviour:
zFailOperation: 0 zFailOperation: 0
m_ShadowTransparentReceive: 0 m_ShadowTransparentReceive: 0
m_RenderingMode: 2 m_RenderingMode: 2
m_DepthPrimingMode: 0 m_DepthPrimingMode: 2
m_CopyDepthMode: 1 m_CopyDepthMode: 1
m_AccurateGbufferNormals: 0 m_AccurateGbufferNormals: 0
m_IntermediateTextureMode: 0 m_IntermediateTextureMode: 0
@ -542,10 +542,11 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Active: 1 m_Active: 1
settings: settings:
BlurMask: 0 BlurMask: 1
Use16Samples: 0
MaskMat: {fileID: 2100000, guid: 1368366248809f24e9a110be3075d1b8, type: 2} MaskMat: {fileID: 2100000, guid: 1368366248809f24e9a110be3075d1b8, type: 2}
BlurMat: {fileID: 0} BlurMat: {fileID: 2100000, guid: 0487cfddca141924d8a1736f6c0b9b7b, type: 2}
BlurIterations: 3
BlurSpread: 0.15
--- !u!114 &6334271670068977784 --- !u!114 &6334271670068977784
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -571,8 +572,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: e32e72b6a3f58a24c9033e2b9275eea0, type: 3} m_Script: {fileID: 11500000, guid: e32e72b6a3f58a24c9033e2b9275eea0, type: 3}
m_Name: ScreenSpaceShadows m_Name: ScreenSpaceShadows
m_EditorClassIdentifier: m_EditorClassIdentifier:
m_Active: 1 m_Active: 0
m_Shader: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, type: 3} m_Shader: {fileID: 4800000, guid: 0f854b35a0cf61a429bd5dcfea30eddd, type: 3}
m_Settings: m_Settings:
UseLowResolution: 1 UseLowResolution: 1
UseLowResolutionPCF: 0 UseLowResolutionPCF: 1

View File

@ -0,0 +1,91 @@
Shader "Unlit/Blur"
{
SubShader
{
ZTest Always Cull Off ZWrite Off
HLSLINCLUDE
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
sampler2D _MainTex;
half4 _MainTex_TexelSize;
float _BlurSize;
struct v2f {
float4 pos : SV_POSITION;
half2 uv[5]: TEXCOORD0;
};
//垂直方向的模糊
v2f vertBlurVertical(uint vertexID: SV_VertexID)
{
v2f o;
o.pos = GetFullScreenTriangleVertexPosition(vertexID);
half2 uv = GetFullScreenTriangleTexCoord(vertexID);
o.uv[0] = uv;
o.uv[1] = uv + float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[2] = uv - float2(0.0, _MainTex_TexelSize.y * 1.0) * _BlurSize;
o.uv[3] = uv + float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
o.uv[4] = uv - float2(0.0, _MainTex_TexelSize.y * 2.0) * _BlurSize;
return o;
}
//水平方向的模糊
v2f vertBlurHorizontal(uint vertexID: SV_VertexID)
{
v2f o;
o.pos = GetFullScreenTriangleVertexPosition(vertexID);
half2 uv = GetFullScreenTriangleTexCoord(vertexID);
o.uv[0] = uv;
o.uv[1] = uv + float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[2] = uv - float2(_MainTex_TexelSize.x * 1.0, 0.0) * _BlurSize;
o.uv[3] = uv + float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
o.uv[4] = uv - float2(_MainTex_TexelSize.x * 2.0, 0.0) * _BlurSize;
return o;
}
half4 fragBlur(v2f i) : SV_Target {
float weight[3] = {0.4026, 0.2442, 0.0545};
half3 sum = tex2D(_MainTex, i.uv[0]).rgb * weight[0];
for (int it = 1; it < 3; it++) {
sum += tex2D(_MainTex, i.uv[it*2-1]).rgb * weight[it];
sum += tex2D(_MainTex, i.uv[it*2]).rgb * weight[it];
}
return half4(sum, 1.0);
}
ENDHLSL
Pass
{
NAME "GAUSSIAN_BLUR_VERTICAL"
HLSLPROGRAM
#pragma vertex vertBlurVertical
#pragma fragment fragBlur
ENDHLSL
}
Pass
{
NAME "GAUSSIAN_BLUR_HORIZONTAL"
HLSLPROGRAM
#pragma vertex vertBlurHorizontal
#pragma fragment fragBlur
ENDHLSL
}
}
}

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ac5e0807b54a94e4a9d8093afd986e43
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
userData:
assetBundleName:
assetBundleVariant:

View File

@ -20,7 +20,6 @@ Shader "Unlit/SoftShadowMask"
#pragma multi_compile _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE #pragma multi_compile _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile_fragment _ _Use16Samples
struct Varyings struct Varyings
{ {
@ -36,12 +35,8 @@ Shader "Unlit/SoftShadowMask"
return o; return o;
} }
#ifdef _Use16Samples
float4 _Offset16[8];
#else
float4 _Offset5[2]; float4 _Offset5[2];
#endif float4 _MaskSizeAndInvRenderSize;
half GetDepth(float2 uv) half GetDepth(float2 uv)
{ {
#if UNITY_REVERSED_Z #if UNITY_REVERSED_Z
@ -66,31 +61,17 @@ Shader "Unlit/SoftShadowMask"
return 1; return 1;
} }
half shadow = SAMPLE_TEXTURE2D_SHADOW(_MainLightShadowmapTexture, sampler_LinearClampCompare, half shadow = 0;
coords.xyz); float2 uv0 = input.uv;
#ifdef _Use16Samples
for (int i = 0; i < 8; ++i)
{
uv = input.uv+ _Offset16[i].xy;
wpos = ComputeWorldSpacePosition(uv, GetDepth(uv), unity_MatrixInvVP);
coords = TransformWorldToShadowCoord(wpos);
shadow += BEYOND_SHADOW_FAR(coords) ? 1 : SAMPLE_TEXTURE2D_SHADOW(_MainLightShadowmapTexture, sampler_LinearClampCompare,coords.xyz);
uv = input.uv+ _Offset16[i].zw;
wpos = ComputeWorldSpacePosition(uv, GetDepth(uv), unity_MatrixInvVP);
coords = TransformWorldToShadowCoord(wpos);
shadow += BEYOND_SHADOW_FAR(coords) ? 1 : SAMPLE_TEXTURE2D_SHADOW(_MainLightShadowmapTexture, sampler_LinearClampCompare, coords.xyz );
}
#else
for (int i = 0; i < 2; ++i) for (int i = 0; i < 2; ++i)
{ {
uv = input.uv + _Offset5[i].xy; uv = uv0 + _Offset5[i].xy;
wpos = ComputeWorldSpacePosition(uv, GetDepth(uv), unity_MatrixInvVP); wpos = ComputeWorldSpacePosition(uv, GetDepth(uv), unity_MatrixInvVP);
coords = TransformWorldToShadowCoord(wpos); coords = TransformWorldToShadowCoord(wpos);
shadow += BEYOND_SHADOW_FAR(coords) ? 1 : SAMPLE_TEXTURE2D_SHADOW(_MainLightShadowmapTexture, sampler_LinearClampCompare, shadow += BEYOND_SHADOW_FAR(coords) ? 1 : SAMPLE_TEXTURE2D_SHADOW(_MainLightShadowmapTexture, sampler_LinearClampCompare,
coords.xyz); coords.xyz);
uv = input.uv + _Offset5[i].zw; uv = uv0 + _Offset5[i].zw;
wpos = ComputeWorldSpacePosition(uv, GetDepth(uv), unity_MatrixInvVP); wpos = ComputeWorldSpacePosition(uv, GetDepth(uv), unity_MatrixInvVP);
coords = TransformWorldToShadowCoord(wpos); coords = TransformWorldToShadowCoord(wpos);
@ -98,8 +79,7 @@ Shader "Unlit/SoftShadowMask"
coords.xyz); coords.xyz);
} }
shadow *= 0.2f; shadow *= 0.25f;
#endif
return shadow; return shadow;
} }

View File

@ -0,0 +1,29 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Unlit_Blur
m_Shader: {fileID: 4800000, guid: ac5e0807b54a94e4a9d8093afd986e43, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs: []
m_Ints: []
m_Floats: []
m_Colors: []
m_BuildTextureStacks: []

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0487cfddca141924d8a1736f6c0b9b7b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -3,6 +3,7 @@ using Unity.Mathematics;
using UnityEngine; using UnityEngine;
using UnityEngine.Rendering; using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal; using UnityEngine.Rendering.Universal;
using static UnityEngine.Rendering.Universal.UniversalRenderPipeline.Profiling.Pipeline;
namespace X.Rendering.Feature namespace X.Rendering.Feature
{ {
@ -12,9 +13,10 @@ namespace X.Rendering.Feature
private class Settings private class Settings
{ {
public bool BlurMask = false; public bool BlurMask = false;
public bool Use16Samples = true;
public Material MaskMat = null; public Material MaskMat = null;
public Material BlurMat = null; public Material BlurMat = null;
public int BlurIterations = 3;
public float BlurSpread = 0.6f;
} }
[SerializeField] [SerializeField]
@ -39,10 +41,10 @@ namespace X.Rendering.Feature
private Settings settings; private Settings settings;
private ProfilingSampler profiler; private ProfilingSampler profiler;
Vector4[] offset16Array = new Vector4[8]; Vector4[] offsetArray = new Vector4[4];
Vector4[] offset5Array = new Vector4[2];
RTHandle softShadowMask; RTHandle softShadowMask;
RTHandle buffer0;
RTHandle buffer1;
public SoftShadowMaskPass(Settings settings) public SoftShadowMaskPass(Settings settings)
{ {
this.settings = settings; this.settings = settings;
@ -58,27 +60,15 @@ namespace X.Rendering.Feature
var w = renderingData.cameraData.cameraTargetDescriptor.width; var w = renderingData.cameraData.cameraTargetDescriptor.width;
var h = renderingData.cameraData.cameraTargetDescriptor.height; var h = renderingData.cameraData.cameraTargetDescriptor.height;
float2 wh = new float2 { x = w, y = h }; float2 wh = new float2 { x = w, y = h };
if (settings.Use16Samples)
{ {
cmd.EnableShaderKeyword("_Use16Samples"); offsetArray[0] = new float4(new float2(-1, 1) / wh, new float2(1, 1) / wh);
for (int i = 0; i < 8; ++i) offsetArray[1] = new float4(new float2(-1, -1) / wh, new float2(1, -1) / wh);
{ offsetArray[2] = new float4(new float2(-2, -2) / wh, new float2(2, 2) / wh);
offsetArray[3] = new float4(new float2(-2, 2) / wh, new float2(2, -2) / wh);
} cmd.SetGlobalVectorArray("_Offset5", offsetArray);
cmd.SetGlobalVectorArray("_Offset16", offset16Array);
} }
else cmd.SetGlobalVector("_MaskSizeAndInvRenderSize", new Vector4(w / 4, h / 4, 1f / w, 1f / h));
{ var desc = new RenderTextureDescriptor()
cmd.DisableShaderKeyword("_Use16Samples");
for (int i = 0; i < 2; ++i)
{
offset5Array[i] = new float4(new float2(-1, 1) / wh, new float2(1, 1) / wh);
offset5Array[i] = new float4(new float2(-1, -1) / wh, new float2(1, -1) / wh);
}
cmd.SetGlobalVectorArray("_Offset5", offset5Array);
}
RenderingUtils.ReAllocateIfNeeded(ref softShadowMask, new RenderTextureDescriptor()
{ {
bindMS = false, bindMS = false,
colorFormat = RenderTextureFormat.R8, colorFormat = RenderTextureFormat.R8,
@ -88,10 +78,37 @@ namespace X.Rendering.Feature
depthBufferBits = 0, depthBufferBits = 0,
dimension = TextureDimension.Tex2D, dimension = TextureDimension.Tex2D,
msaaSamples = 1, msaaSamples = 1,
}); };
RenderingUtils.ReAllocateIfNeeded(ref softShadowMask, desc);
cmd.SetGlobalTexture("_CameraDepthTexture", renderingData.cameraData.renderer.cameraDepthTargetHandle);
cmd.SetRenderTarget(softShadowMask); cmd.SetRenderTarget(softShadowMask);
cmd.DrawProcedural(Matrix4x4.identity, settings.MaskMat, 0, MeshTopology.Triangles, 3); cmd.DrawProcedural(Matrix4x4.identity, settings.MaskMat, 0, MeshTopology.Triangles, 3);
cmd.SetGlobalTexture(SoftShadowMaskTextureId, softShadowMask); if (settings.BlurMask)
{
cmd.BeginSample("SoftShadowMask Blur");
//desc.memoryless = RenderTextureMemoryless.Color;
RenderingUtils.ReAllocateIfNeeded(ref buffer0, desc, name: "buffer0");
RenderingUtils.ReAllocateIfNeeded(ref buffer1, desc, name: "buffer1");
cmd.SetGlobalTexture("_MainTex", softShadowMask);
for (int i = 0; i < settings.BlurIterations; i++)
{
settings.BlurMat.SetFloat("_BlurSize", i * settings.BlurSpread);
cmd.SetRenderTarget(buffer0);
cmd.DrawProcedural(Matrix4x4.identity, settings.BlurMat, 0, MeshTopology.Triangles, 3);
cmd.SetGlobalTexture("_MainTex", buffer0);
cmd.SetRenderTarget(buffer1);
cmd.DrawProcedural(Matrix4x4.identity, settings.BlurMat, 1, MeshTopology.Triangles, 3);
cmd.SetGlobalTexture("_MainTex", buffer1);
}
cmd.EndSample("SoftShadowMask Blur");
cmd.SetGlobalTexture(SoftShadowMaskTextureId, buffer1);
}
else
{
cmd.SetGlobalTexture(SoftShadowMaskTextureId, softShadowMask);
}
} }
public override void OnFinishCameraStackRendering(CommandBuffer cmd) public override void OnFinishCameraStackRendering(CommandBuffer cmd)

View File

@ -338,6 +338,23 @@ half4 UniversalFragmentPBR(InputData inputData, SurfaceData surfaceData)
lightingData.vertexLightingColor += inputData.vertexLighting * brdfData.diffuse; lightingData.vertexLightingColor += inputData.vertexLighting * brdfData.diffuse;
#endif #endif
// #if defined(_SCREEN_SPACE_SHADOW_LOW_RESOLUTION_PCF)
// half realtimeShadow = half(SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_PointClamp, inputData.normalizedScreenSpaceUV.xy).x);
// UNITY_BRANCH
// if(abs(realtimeShadow - 0.5) < 0.499)
// {
// return float4(1, 0, 0, 1);
// }
// #endif
// #if defined(_SOFTSHADOW_MASK)
// half realtimeShadow = half(SAMPLE_TEXTURE2D(_SoftShadowMaskTexture, sampler_PointClamp, inputData.normalizedScreenSpaceUV.xy).x);
// UNITY_BRANCH
// if(abs(realtimeShadow - 0.5) < 0.499)
// {
// return float4(1, 0, 0, 1);
// }
// #endif
#if REAL_IS_HALF #if REAL_IS_HALF
// Clamp any half.inf+ to HALF_MAX // Clamp any half.inf+ to HALF_MAX
return min(CalculateFinalColor(lightingData, surfaceData.alpha), HALF_MAX); return min(CalculateFinalColor(lightingData, surfaceData.alpha), HALF_MAX);

View File

@ -122,6 +122,19 @@ Light GetMainLight(float4 shadowCoord)
return light; return light;
} }
Light GetMainLight(float4 shadowCoord, float2 screenUV, float3 positionWS, half4 shadowMask)
{
Light light = GetMainLight();
light.shadowAttenuation = MainLightShadow(shadowCoord, screenUV, positionWS, shadowMask, _MainLightOcclusionProbes);
#if defined(_LIGHT_COOKIES)
real3 cookieColor = SampleMainLightCookie(positionWS);
light.color *= cookieColor;
#endif
return light;
}
Light GetMainLight(float4 shadowCoord, float3 positionWS, half4 shadowMask) Light GetMainLight(float4 shadowCoord, float3 positionWS, half4 shadowMask)
{ {
Light light = GetMainLight(); Light light = GetMainLight();
@ -137,7 +150,7 @@ Light GetMainLight(float4 shadowCoord, float3 positionWS, half4 shadowMask)
Light GetMainLight(InputData inputData, half4 shadowMask, AmbientOcclusionFactor aoFactor) Light GetMainLight(InputData inputData, half4 shadowMask, AmbientOcclusionFactor aoFactor)
{ {
Light light = GetMainLight(inputData.shadowCoord, inputData.positionWS, shadowMask); Light light = GetMainLight(inputData.shadowCoord, inputData.normalizedScreenSpaceUV, inputData.positionWS, shadowMask);
#if defined(_SCREEN_SPACE_OCCLUSION) && !defined(_SURFACE_TYPE_TRANSPARENT) #if defined(_SCREEN_SPACE_OCCLUSION) && !defined(_SURFACE_TYPE_TRANSPARENT)
if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_AMBIENT_OCCLUSION)) if (IsLightingFeatureEnabled(DEBUGLIGHTINGFEATUREFLAGS_AMBIENT_OCCLUSION))

View File

@ -10,17 +10,17 @@
#define MAX_SHADOW_CASCADES 4 #define MAX_SHADOW_CASCADES 4
#if !defined(_RECEIVE_SHADOWS_OFF) #if !defined(_RECEIVE_SHADOWS_OFF)
#if defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN) #if defined(_MAIN_LIGHT_SHADOWS) || defined(_MAIN_LIGHT_SHADOWS_CASCADE) || defined(_MAIN_LIGHT_SHADOWS_SCREEN)
#define MAIN_LIGHT_CALCULATE_SHADOWS #define MAIN_LIGHT_CALCULATE_SHADOWS
#if defined(_MAIN_LIGHT_SHADOWS) || (defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)) #if defined(_MAIN_LIGHT_SHADOWS) || (defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT))
#define REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR #define REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR
#endif #endif
#endif #endif
#if defined(_ADDITIONAL_LIGHT_SHADOWS) #if defined(_ADDITIONAL_LIGHT_SHADOWS)
#define ADDITIONAL_LIGHT_CALCULATE_SHADOWS #define ADDITIONAL_LIGHT_CALCULATE_SHADOWS
#endif #endif
#endif #endif
#if defined(UNITY_DOTS_INSTANCING_ENABLED) #if defined(UNITY_DOTS_INSTANCING_ENABLED)
@ -36,7 +36,7 @@
#if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON) #if defined(SHADOWS_SHADOWMASK) && defined(LIGHTMAP_ON)
#define SAMPLE_SHADOWMASK(uv) SAMPLE_TEXTURE2D_LIGHTMAP(SHADOWMASK_NAME, SHADOWMASK_SAMPLER_NAME, uv SHADOWMASK_SAMPLE_EXTRA_ARGS); #define SAMPLE_SHADOWMASK(uv) SAMPLE_TEXTURE2D_LIGHTMAP(SHADOWMASK_NAME, SHADOWMASK_SAMPLER_NAME, uv SHADOWMASK_SAMPLE_EXTRA_ARGS);
#elif !defined (LIGHTMAP_ON) #elif !defined (LIGHTMAP_ON)
#define SAMPLE_SHADOWMASK(uv) unity_ProbesOcclusion; #define SAMPLE_SHADOWMASK(uv) unity_ProbesOcclusion;
#else #else
#define SAMPLE_SHADOWMASK(uv) half4(1, 1, 1, 1); #define SAMPLE_SHADOWMASK(uv) half4(1, 1, 1, 1);
#endif #endif
@ -49,6 +49,7 @@
SCREENSPACE_TEXTURE(_ScreenSpaceShadowmapTexture); SCREENSPACE_TEXTURE(_ScreenSpaceShadowmapTexture);
TEXTURE2D(_SoftShadowMaskTexture);
TEXTURE2D_SHADOW(_MainLightShadowmapTexture); TEXTURE2D_SHADOW(_MainLightShadowmapTexture);
TEXTURE2D_SHADOW(_AdditionalLightsShadowmapTexture); TEXTURE2D_SHADOW(_AdditionalLightsShadowmapTexture);
SAMPLER_CMP(sampler_LinearClampCompare); SAMPLER_CMP(sampler_LinearClampCompare);
@ -56,48 +57,50 @@ SAMPLER_CMP(sampler_LinearClampCompare);
// GLES3 causes a performance regression in some devices when using CBUFFER. // GLES3 causes a performance regression in some devices when using CBUFFER.
#ifndef SHADER_API_GLES3 #ifndef SHADER_API_GLES3
CBUFFER_START(LightShadows) CBUFFER_START(LightShadows)
#endif #endif
// Last cascade is initialized with a no-op matrix. It always transforms // Last cascade is initialized with a no-op matrix. It always transforms
// shadow coord to half3(0, 0, NEAR_PLANE). We use this trick to avoid // shadow coord to half3(0, 0, NEAR_PLANE). We use this trick to avoid
// branching since ComputeCascadeIndex can return cascade index = MAX_SHADOW_CASCADES // branching since ComputeCascadeIndex can return cascade index = MAX_SHADOW_CASCADES
float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1]; float4x4 _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1];
float4 _CascadeShadowSplitSpheres0; float4 _CascadeShadowSplitSpheres0;
float4 _CascadeShadowSplitSpheres1; float4 _CascadeShadowSplitSpheres1;
float4 _CascadeShadowSplitSpheres2; float4 _CascadeShadowSplitSpheres2;
float4 _CascadeShadowSplitSpheres3; float4 _CascadeShadowSplitSpheres3;
float4 _CascadeShadowSplitSphereRadii; float4 _CascadeShadowSplitSphereRadii;
float4 _MainLightShadowOffset0; // xy: offset0, zw: offset1 float4 _MainLightShadowOffset0; // xy: offset0, zw: offset1
float4 _MainLightShadowOffset1; // xy: offset2, zw: offset3 float4 _MainLightShadowOffset1; // xy: offset2, zw: offset3
float4 _MainLightShadowParams; // (x: shadowStrength, y: >= 1.0 if soft shadows, 0.0 otherwise, z: main light fade scale, w: main light fade bias) float4 _MainLightShadowParams;
float4 _MainLightShadowmapSize; // (xy: 1/width and 1/height, zw: width and height) // (x: shadowStrength, y: >= 1.0 if soft shadows, 0.0 otherwise, z: main light fade scale, w: main light fade bias)
float4 _MainLightShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
float4 _AdditionalShadowOffset0; // xy: offset0, zw: offset1 float4 _AdditionalShadowOffset0; // xy: offset0, zw: offset1
float4 _AdditionalShadowOffset1; // xy: offset2, zw: offset3 float4 _AdditionalShadowOffset1; // xy: offset2, zw: offset3
float4 _AdditionalShadowFadeParams; // x: additional light fade scale, y: additional light fade bias, z: 0.0, w: 0.0) float4 _AdditionalShadowFadeParams;
float4 _AdditionalShadowmapSize; // (xy: 1/width and 1/height, zw: width and height) // x: additional light fade scale, y: additional light fade bias, z: 0.0, w: 0.0)
float4 _AdditionalShadowmapSize; // (xy: 1/width and 1/height, zw: width and height)
#if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS) #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
#if !USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA #if !USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
// Point lights can use 6 shadow slices. Some mobile GPUs performance decrease drastically with uniform // Point lights can use 6 shadow slices. Some mobile GPUs performance decrease drastically with uniform
// blocks bigger than 8kb while others have a 64kb max uniform block size. This number ensures size of buffer // blocks bigger than 8kb while others have a 64kb max uniform block size. This number ensures size of buffer
// AdditionalLightShadows stays reasonable. It also avoids shader compilation errors on SHADER_API_GLES30 // AdditionalLightShadows stays reasonable. It also avoids shader compilation errors on SHADER_API_GLES30
// devices where max number of uniforms per shader GL_MAX_FRAGMENT_UNIFORM_VECTORS is low (224) // devices where max number of uniforms per shader GL_MAX_FRAGMENT_UNIFORM_VECTORS is low (224)
float4 _AdditionalShadowParams[MAX_VISIBLE_LIGHTS]; // Per-light data float4 _AdditionalShadowParams[MAX_VISIBLE_LIGHTS]; // Per-light data
float4x4 _AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS]; // Per-shadow-slice-data float4x4 _AdditionalLightsWorldToShadow[MAX_VISIBLE_LIGHTS]; // Per-shadow-slice-data
#endif #endif
#endif #endif
#ifndef SHADER_API_GLES3 #ifndef SHADER_API_GLES3
CBUFFER_END CBUFFER_END
#endif #endif
#if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS) #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
StructuredBuffer<float4> _AdditionalShadowParams_SSBO; // Per-light data - TODO: test if splitting _AdditionalShadowParams_SSBO[lightIndex].w into a separate StructuredBuffer<int> buffer is faster StructuredBuffer<float4> _AdditionalShadowParams_SSBO; // Per-light data - TODO: test if splitting _AdditionalShadowParams_SSBO[lightIndex].w into a separate StructuredBuffer<int> buffer is faster
StructuredBuffer<float4x4> _AdditionalLightsWorldToShadow_SSBO; // Per-shadow-slice-data - A shadow casting light can have 6 shadow slices (if it's a point light) StructuredBuffer<float4x4> _AdditionalLightsWorldToShadow_SSBO; // Per-shadow-slice-data - A shadow casting light can have 6 shadow slices (if it's a point light)
#endif #endif
#endif #endif
float4 _ShadowBias; // x: depth bias, y: normal bias float4 _ShadowBias; // x: depth bias, y: normal bias
@ -167,14 +170,14 @@ half4 GetMainLightShadowParams()
half4 GetAdditionalLightShadowParams(int lightIndex) half4 GetAdditionalLightShadowParams(int lightIndex)
{ {
#if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS) #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
return _AdditionalShadowParams_SSBO[lightIndex]; return _AdditionalShadowParams_SSBO[lightIndex];
#else
return _AdditionalShadowParams[lightIndex];
#endif
#else #else
// Same defaults as set in AdditionalLightsShadowCasterPass.cs return _AdditionalShadowParams[lightIndex];
return half4(0, 0, 0, -1); #endif
#else
// Same defaults as set in AdditionalLightsShadowCasterPass.cs
return half4(0, 0, 0, -1);
#endif #endif
} }
@ -185,92 +188,125 @@ half SampleScreenSpaceShadowmap(float4 shadowCoord)
// The stereo transform has to happen after the manual perspective divide // The stereo transform has to happen after the manual perspective divide
shadowCoord.xy = UnityStereoTransformScreenSpaceTex(shadowCoord.xy); shadowCoord.xy = UnityStereoTransformScreenSpaceTex(shadowCoord.xy);
#if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED) #if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
half attenuation = SAMPLE_TEXTURE2D_ARRAY(_ScreenSpaceShadowmapTexture, sampler_PointClamp, shadowCoord.xy, unity_StereoEyeIndex).x; half attenuation = SAMPLE_TEXTURE2D_ARRAY(_ScreenSpaceShadowmapTexture, sampler_PointClamp, shadowCoord.xy, unity_StereoEyeIndex).x;
#else #else
#if defined(_SCREEN_SPACE_SHADOW_LOW_RESOLUTION_PCF)
// mip 可能造成更多 PCF
half attenuation = half(SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_PointClamp, float3(shadowCoord.xy, 2)).x);
#else
half attenuation = half(SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_PointClamp, shadowCoord.xy).x); half attenuation = half(SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_PointClamp, shadowCoord.xy).x);
#endif #endif
#endif
return attenuation; return attenuation;
} }
real SampleShadowmapFilteredLowQuality(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData) real SampleShadowmapFilteredLowQuality(
TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
{ {
// 4-tap hardware comparison // 4-tap hardware comparison
real4 attenuation4; real4 attenuation4;
attenuation4.x = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset0.xy, 0))); attenuation4.x = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
attenuation4.y = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset0.zw, 0))); shadowCoord.xyz + float3(samplingData.shadowOffset0.xy, 0)));
attenuation4.z = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset1.xy, 0))); attenuation4.y = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
attenuation4.w = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz + float3(samplingData.shadowOffset1.zw, 0))); shadowCoord.xyz + float3(samplingData.shadowOffset0.zw, 0)));
attenuation4.z = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
shadowCoord.xyz + float3(samplingData.shadowOffset1.xy, 0)));
attenuation4.w = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
shadowCoord.xyz + float3(samplingData.shadowOffset1.zw, 0)));
return dot(attenuation4, real(0.25)); return dot(attenuation4, real(0.25));
} }
real SampleShadowmapFilteredMediumQuality(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData) real SampleShadowmapFilteredMediumQuality(
TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
{ {
real fetchesWeights[9]; real fetchesWeights[9];
real2 fetchesUV[9]; real2 fetchesUV[9];
SampleShadow_ComputeSamples_Tent_5x5(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV); SampleShadow_ComputeSamples_Tent_5x5(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
return fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[0].xy, shadowCoord.z)) return fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[1].xy, shadowCoord.z)) float3(fetchesUV[0].xy, shadowCoord.z))
+ fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[2].xy, shadowCoord.z)) + fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[3].xy, shadowCoord.z)) float3(fetchesUV[1].xy, shadowCoord.z))
+ fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[4].xy, shadowCoord.z)) + fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[5].xy, shadowCoord.z)) float3(fetchesUV[2].xy, shadowCoord.z))
+ fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[6].xy, shadowCoord.z)) + fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[7].xy, shadowCoord.z)) float3(fetchesUV[3].xy, shadowCoord.z))
+ fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[8].xy, shadowCoord.z)); + fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[4].xy, shadowCoord.z))
+ fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[5].xy, shadowCoord.z))
+ fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[6].xy, shadowCoord.z))
+ fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[7].xy, shadowCoord.z))
+ fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[8].xy, shadowCoord.z));
} }
real SampleShadowmapFilteredHighQuality(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData) real SampleShadowmapFilteredHighQuality(
TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
{ {
real fetchesWeights[16]; real fetchesWeights[16];
real2 fetchesUV[16]; real2 fetchesUV[16];
SampleShadow_ComputeSamples_Tent_7x7(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV); SampleShadow_ComputeSamples_Tent_7x7(samplingData.shadowmapSize, shadowCoord.xy, fetchesWeights, fetchesUV);
return fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[0].xy, shadowCoord.z)) return fetchesWeights[0] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[1].xy, shadowCoord.z)) float3(fetchesUV[0].xy, shadowCoord.z))
+ fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[2].xy, shadowCoord.z)) + fetchesWeights[1] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[3].xy, shadowCoord.z)) float3(fetchesUV[1].xy, shadowCoord.z))
+ fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[4].xy, shadowCoord.z)) + fetchesWeights[2] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[5].xy, shadowCoord.z)) float3(fetchesUV[2].xy, shadowCoord.z))
+ fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[6].xy, shadowCoord.z)) + fetchesWeights[3] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[7].xy, shadowCoord.z)) float3(fetchesUV[3].xy, shadowCoord.z))
+ fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[8].xy, shadowCoord.z)) + fetchesWeights[4] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[9] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[9].xy, shadowCoord.z)) float3(fetchesUV[4].xy, shadowCoord.z))
+ fetchesWeights[10] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[10].xy, shadowCoord.z)) + fetchesWeights[5] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[11] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[11].xy, shadowCoord.z)) float3(fetchesUV[5].xy, shadowCoord.z))
+ fetchesWeights[12] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[12].xy, shadowCoord.z)) + fetchesWeights[6] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[13] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[13].xy, shadowCoord.z)) float3(fetchesUV[6].xy, shadowCoord.z))
+ fetchesWeights[14] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[14].xy, shadowCoord.z)) + fetchesWeights[7] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
+ fetchesWeights[15] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, float3(fetchesUV[15].xy, shadowCoord.z)); float3(fetchesUV[7].xy, shadowCoord.z))
+ fetchesWeights[8] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[8].xy, shadowCoord.z))
+ fetchesWeights[9] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[9].xy, shadowCoord.z))
+ fetchesWeights[10] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[10].xy, shadowCoord.z))
+ fetchesWeights[11] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[11].xy, shadowCoord.z))
+ fetchesWeights[12] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[12].xy, shadowCoord.z))
+ fetchesWeights[13] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[13].xy, shadowCoord.z))
+ fetchesWeights[14] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[14].xy, shadowCoord.z))
+ fetchesWeights[15] * SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap,
float3(fetchesUV[15].xy, shadowCoord.z));
} }
real SampleShadowmapFiltered(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData) real SampleShadowmapFiltered(
TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData)
{ {
real attenuation = real(1.0); real attenuation = real(1.0);
if (samplingData.softShadowQuality == SOFT_SHADOW_QUALITY_LOW) if (samplingData.softShadowQuality == SOFT_SHADOW_QUALITY_LOW)
{ {
attenuation = SampleShadowmapFilteredLowQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData); attenuation = SampleShadowmapFilteredLowQuality(
TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
} }
else if(samplingData.softShadowQuality == SOFT_SHADOW_QUALITY_MEDIUM) else if (samplingData.softShadowQuality == SOFT_SHADOW_QUALITY_MEDIUM)
{ {
attenuation = SampleShadowmapFilteredMediumQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData); attenuation = SampleShadowmapFilteredMediumQuality(
TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
} }
else // SOFT_SHADOW_QUALITY_HIGH else // SOFT_SHADOW_QUALITY_HIGH
{ {
attenuation = SampleShadowmapFilteredHighQuality(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData); attenuation = SampleShadowmapFilteredHighQuality(
TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData);
} }
return attenuation; return attenuation;
} }
real SampleShadowmap(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData, half4 shadowParams, bool isPerspectiveProjection = true) real SampleShadowmap(
TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float4 shadowCoord, ShadowSamplingData samplingData,
half4 shadowParams, bool isPerspectiveProjection = true)
{ {
// Compiler will optimize this branch away as long as isPerspectiveProjection is known at compile time // Compiler will optimize this branch away as long as isPerspectiveProjection is known at compile time
if (isPerspectiveProjection) if (isPerspectiveProjection)
@ -296,7 +332,7 @@ real SampleShadowmap(TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), float
attenuation = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz)); attenuation = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz));
} }
#else #else
attenuation = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz)); attenuation = real(SAMPLE_TEXTURE2D_SHADOW(ShadowMap, sampler_ShadowMap, shadowCoord.xyz));
#endif #endif
attenuation = LerpWhiteTo(attenuation, shadowStrength); attenuation = LerpWhiteTo(attenuation, shadowStrength);
@ -312,7 +348,8 @@ half ComputeCascadeIndex(float3 positionWS)
float3 fromCenter1 = positionWS - _CascadeShadowSplitSpheres1.xyz; float3 fromCenter1 = positionWS - _CascadeShadowSplitSpheres1.xyz;
float3 fromCenter2 = positionWS - _CascadeShadowSplitSpheres2.xyz; float3 fromCenter2 = positionWS - _CascadeShadowSplitSpheres2.xyz;
float3 fromCenter3 = positionWS - _CascadeShadowSplitSpheres3.xyz; float3 fromCenter3 = positionWS - _CascadeShadowSplitSpheres3.xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3)); float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1),
dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
half4 weights = half4(distances2 < _CascadeShadowSplitSphereRadii); half4 weights = half4(distances2 < _CascadeShadowSplitSphereRadii);
weights.yzw = saturate(weights.yzw - weights.xyz); weights.yzw = saturate(weights.yzw - weights.xyz);
@ -322,11 +359,11 @@ half ComputeCascadeIndex(float3 positionWS)
float4 TransformWorldToShadowCoord(float3 positionWS) float4 TransformWorldToShadowCoord(float3 positionWS)
{ {
#ifdef _MAIN_LIGHT_SHADOWS_CASCADE #ifdef _MAIN_LIGHT_SHADOWS_CASCADE
half cascadeIndex = ComputeCascadeIndex(positionWS); half cascadeIndex = ComputeCascadeIndex(positionWS);
#else #else
half cascadeIndex = half(0.0); half cascadeIndex = half(0.0);
#endif #endif
float4 shadowCoord = mul(_MainLightWorldToShadow[cascadeIndex], float4(positionWS, 1.0)); float4 shadowCoord = mul(_MainLightWorldToShadow[cascadeIndex], float4(positionWS, 1.0));
@ -336,8 +373,8 @@ float4 TransformWorldToShadowCoord(float3 positionWS)
half MainLightRealtimeShadow(float4 shadowCoord) half MainLightRealtimeShadow(float4 shadowCoord)
{ {
#if !defined(MAIN_LIGHT_CALCULATE_SHADOWS) #if !defined(MAIN_LIGHT_CALCULATE_SHADOWS)
return half(1.0); return half(1.0);
#elif defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT) #elif ( defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT))
float attenuation = SampleScreenSpaceShadowmap(shadowCoord); float attenuation = SampleScreenSpaceShadowmap(shadowCoord);
return attenuation; return attenuation;
#else #else
@ -370,15 +407,15 @@ half AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS, half3 ligh
shadowSliceIndex += cubemapFaceId; shadowSliceIndex += cubemapFaceId;
} }
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
float4 shadowCoord = mul(_AdditionalLightsWorldToShadow_SSBO[shadowSliceIndex], float4(positionWS, 1.0)); float4 shadowCoord = mul(_AdditionalLightsWorldToShadow_SSBO[shadowSliceIndex], float4(positionWS, 1.0));
#else #else
float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[shadowSliceIndex], float4(positionWS, 1.0)); float4 shadowCoord = mul(_AdditionalLightsWorldToShadow[shadowSliceIndex], float4(positionWS, 1.0));
#endif #endif
return SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_LinearClampCompare), shadowCoord, shadowSamplingData, shadowParams, true); return SampleShadowmap(TEXTURE2D_ARGS(_AdditionalLightsShadowmapTexture, sampler_LinearClampCompare), shadowCoord, shadowSamplingData, shadowParams, true);
#else #else
return half(1.0); return half(1.0);
#endif #endif
} }
@ -400,17 +437,17 @@ half GetAdditionalLightShadowFade(float3 positionWS)
float fade = saturate(distanceCamToPixel2 * float(_AdditionalShadowFadeParams.x) + float(_AdditionalShadowFadeParams.y)); float fade = saturate(distanceCamToPixel2 * float(_AdditionalShadowFadeParams.x) + float(_AdditionalShadowFadeParams.y));
return half(fade); return half(fade);
#else #else
return half(1.0); return half(1.0);
#endif #endif
} }
half MixRealtimeAndBakedShadows(half realtimeShadow, half bakedShadow, half shadowFade) half MixRealtimeAndBakedShadows(half realtimeShadow, half bakedShadow, half shadowFade)
{ {
#if defined(LIGHTMAP_SHADOW_MIXING) #if defined(LIGHTMAP_SHADOW_MIXING)
return min(lerp(realtimeShadow, 1, shadowFade), bakedShadow); return min(lerp(realtimeShadow, 1, shadowFade), bakedShadow);
#else #else
return lerp(realtimeShadow, bakedShadow, shadowFade); return lerp(realtimeShadow, bakedShadow, shadowFade);
#endif #endif
} }
half BakedShadow(half4 shadowMask, half4 occlusionProbeChannels) half BakedShadow(half4 shadowMask, half4 occlusionProbeChannels)
@ -423,61 +460,94 @@ half BakedShadow(half4 shadowMask, half4 occlusionProbeChannels)
return bakedShadow; return bakedShadow;
} }
half MainLightShadow(float4 shadowCoord, float3 positionWS, half4 shadowMask, half4 occlusionProbeChannels) half MainLightShadow(float4 shadowCoord, float2 screenUV, float3 positionWS, half4 shadowMask,
half4 occlusionProbeChannels)
{ {
half realtimeShadow = MainLightRealtimeShadow(shadowCoord); #if defined(_SCREEN_SPACE_SHADOW_LOW_RESOLUTION_PCF)
#if defined(_MAIN_LIGHT_SHADOWS_SCREEN) && defined(_SCREEN_SPACE_SHADOW_LOW_RESOLUTION_PCF) // mip 可能造成更多 PCF
half realtimeShadow = half(SAMPLE_TEXTURE2D(_ScreenSpaceShadowmapTexture, sampler_PointClamp, float3(screenUV.xy, 2)).x);
UNITY_BRANCH UNITY_BRANCH
if(abs(realtimeShadow - 0.5) < 0.499) if(abs(realtimeShadow - 0.5) < 0.499)
{ {
float4 shadowCoord1 = TransformWorldToShadowCoord(positionWS);
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData(); ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half4 shadowParams = GetMainLightShadowParams(); half4 shadowParams = GetMainLightShadowParams();
realtimeShadow = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_LinearClampCompare), shadowCoord1, shadowSamplingData, shadowParams, false); realtimeShadow = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_LinearClampCompare), shadowCoord, shadowSamplingData, shadowParams, false);
} }
#elif defined(_SOFTSHADOW_MASK)
half realtimeShadow = half(SAMPLE_TEXTURE2D(_SoftShadowMaskTexture, sampler_PointClamp, screenUV.xy).x);
UNITY_BRANCH
if(abs(realtimeShadow - 0.5) < 0.499)
{
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half4 shadowParams = GetMainLightShadowParams();
realtimeShadow = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_LinearClampCompare), shadowCoord, shadowSamplingData, shadowParams, false);
}
#else
half realtimeShadow = MainLightRealtimeShadow(shadowCoord);
#endif #endif
#ifdef CALCULATE_BAKED_SHADOWS #ifdef CALCULATE_BAKED_SHADOWS
half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels); half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
#else #else
half bakedShadow = half(1.0); half bakedShadow = half(1.0);
#endif #endif
#ifdef MAIN_LIGHT_CALCULATE_SHADOWS #ifdef MAIN_LIGHT_CALCULATE_SHADOWS
half shadowFade = GetMainLightShadowFade(positionWS); half shadowFade = GetMainLightShadowFade(positionWS);
#else #else
half shadowFade = half(1.0); half shadowFade = half(1.0);
#endif #endif
return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade); return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
} }
half AdditionalLightShadow(int lightIndex, float3 positionWS, half3 lightDirection, half4 shadowMask, half4 occlusionProbeChannels) half MainLightShadow(float4 shadowCoord, float3 positionWS, half4 shadowMask, half4 occlusionProbeChannels)
{
half realtimeShadow = MainLightRealtimeShadow(shadowCoord);
#ifdef CALCULATE_BAKED_SHADOWS
half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
#else
half bakedShadow = half(1.0);
#endif
#ifdef MAIN_LIGHT_CALCULATE_SHADOWS
half shadowFade = GetMainLightShadowFade(positionWS);
#else
half shadowFade = half(1.0);
#endif
return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
}
half AdditionalLightShadow(int lightIndex, float3 positionWS, half3 lightDirection, half4 shadowMask,
half4 occlusionProbeChannels)
{ {
half realtimeShadow = AdditionalLightRealtimeShadow(lightIndex, positionWS, lightDirection); half realtimeShadow = AdditionalLightRealtimeShadow(lightIndex, positionWS, lightDirection);
#ifdef CALCULATE_BAKED_SHADOWS #ifdef CALCULATE_BAKED_SHADOWS
half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels); half bakedShadow = BakedShadow(shadowMask, occlusionProbeChannels);
#else #else
half bakedShadow = half(1.0); half bakedShadow = half(1.0);
#endif #endif
#ifdef ADDITIONAL_LIGHT_CALCULATE_SHADOWS #ifdef ADDITIONAL_LIGHT_CALCULATE_SHADOWS
half shadowFade = GetAdditionalLightShadowFade(positionWS); half shadowFade = GetAdditionalLightShadowFade(positionWS);
#else #else
half shadowFade = half(1.0); half shadowFade = half(1.0);
#endif #endif
return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade); return MixRealtimeAndBakedShadows(realtimeShadow, bakedShadow, shadowFade);
} }
float4 GetShadowCoord(VertexPositionInputs vertexInput) float4 GetShadowCoord(VertexPositionInputs vertexInput)
{ {
#if defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT) #if defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)
return ComputeScreenPos(vertexInput.positionCS); return ComputeScreenPos(vertexInput.positionCS);
#else #else
return TransformWorldToShadowCoord(vertexInput.positionWS); return TransformWorldToShadowCoord(vertexInput.positionWS);
#endif #endif
} }
float3 ApplyShadowBias(float3 positionWS, float3 normalWS, float3 lightDirection) float3 ApplyShadowBias(float3 positionWS, float3 normalWS, float3 lightDirection)
@ -525,21 +595,24 @@ half GetMainLightShadowStrength()
half GetAdditionalLightShadowStrenth(int lightIndex) half GetAdditionalLightShadowStrenth(int lightIndex)
{ {
#if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS) #if defined(ADDITIONAL_LIGHT_CALCULATE_SHADOWS)
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA #if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
return _AdditionalShadowParams_SSBO[lightIndex].x; return _AdditionalShadowParams_SSBO[lightIndex].x;
#else
return _AdditionalShadowParams[lightIndex].x;
#endif
#else #else
return half(1.0); return _AdditionalShadowParams[lightIndex].x;
#endif
#else
return half(1.0);
#endif #endif
} }
// Deprecated: Use SampleShadowmap that takes shadowParams instead of strength. // Deprecated: Use SampleShadowmap that takes shadowParams instead of strength.
real SampleShadowmap(float4 shadowCoord, TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap), ShadowSamplingData samplingData, half shadowStrength, bool isPerspectiveProjection = true) real SampleShadowmap(float4 shadowCoord, TEXTURE2D_SHADOW_PARAM(ShadowMap, sampler_ShadowMap),
ShadowSamplingData samplingData, half shadowStrength, bool isPerspectiveProjection = true)
{ {
half4 shadowParams = half4(shadowStrength, 1.0, 0.0, 0.0); half4 shadowParams = half4(shadowStrength, 1.0, 0.0, 0.0);
return SampleShadowmap(TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData, shadowParams, isPerspectiveProjection); return SampleShadowmap(
TEXTURE2D_SHADOW_ARGS(ShadowMap, sampler_ShadowMap), shadowCoord, samplingData, shadowParams,
isPerspectiveProjection);
} }
// Deprecated: Use AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS, half3 lightDirection) in Shadows.hlsl instead, as it supports Point Light shadows // Deprecated: Use AdditionalLightRealtimeShadow(int lightIndex, float3 positionWS, half3 lightDirection) in Shadows.hlsl instead, as it supports Point Light shadows

View File

@ -135,6 +135,7 @@ Shader "Universal Render Pipeline/Lit"
// Universal Pipeline keywords // Universal Pipeline keywords
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN #pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#pragma multi_compile_fragment _ _SCREEN_SPACE_SHADOW_LOW_RESOLUTION_PCF #pragma multi_compile_fragment _ _SCREEN_SPACE_SHADOW_LOW_RESOLUTION_PCF
#pragma multi_compile_fragment _ _SOFTSHADOW_MASK
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX #pragma multi_compile _ EVALUATE_SH_MIXED EVALUATE_SH_VERTEX
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS #pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
@ -168,7 +169,7 @@ Shader "Universal Render Pipeline/Lit"
#include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl" #include_with_pragmas "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DOTS.hlsl"
#pragma multi_compile_vertex _ ENABLE_VS_SKINNING #pragma multi_compile_vertex _ ENABLE_VS_SKINNING
#pragma enable_d3d11_debug_symbols
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl" #include "Packages/com.unity.render-pipelines.universal/Shaders/LitForwardPass.hlsl"
ENDHLSL ENDHLSL

View File

@ -232,6 +232,7 @@ void LitPassFragment(
#endif #endif
half4 color = UniversalFragmentPBR(inputData, surfaceData); half4 color = UniversalFragmentPBR(inputData, surfaceData);
color.rgb = MixFog(color.rgb, inputData.fogCoord); color.rgb = MixFog(color.rgb, inputData.fogCoord);
color.a = OutputAlpha(color.a, IsSurfaceTypeTransparent(_Surface)); color.a = OutputAlpha(color.a, IsSurfaceTypeTransparent(_Surface));