103 lines
4.8 KiB
GLSL
103 lines
4.8 KiB
GLSL
// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA)
|
|
// Copyright (c) 2021 Kuroneko ShaderLab Limited
|
|
|
|
// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
|
|
|
|
Shader "Hidden/NiloToon/AverageShadowTestRT"
|
|
{
|
|
HLSLINCLUDE
|
|
|
|
// we need URP's shadow map related keywords
|
|
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
|
|
|
|
#if defined(_MAIN_LIGHT_SHADOWS_SCREEN)
|
|
// use _SURFACE_TYPE_TRANSPARENT to force URP Shadow running the classic sample path in Shadows.hlsl's half MainLightRealtimeShadow(float4 shadowCoord){...}
|
|
// since screen space shadow will not work for this shader
|
|
#define _SURFACE_TYPE_TRANSPARENT
|
|
#endif
|
|
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
|
#include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
|
|
|
|
// for most game type, 128 is a big enough number, but still not affect performance
|
|
#define MAX_CHARACTER_COUNT 128
|
|
#define MAX_DATA_ARRAY_SIZE 512 // = 128 characters * 4 data slot
|
|
#define TEST_COUNT 5 // usually 5 is smooth enough, it means (5+1+5)^3 = total of 1331 shadow tests for 1 character per frame
|
|
|
|
float _GlobalAverageShadowTestBoundingSphereDataArray[MAX_DATA_ARRAY_SIZE];
|
|
float _GlobalAverageShadowStrength;
|
|
|
|
half Frag(Varyings input) : SV_Target
|
|
{
|
|
// SHADER_LIBRARY_VERSION_MAJOR is deprecated for Unity2022.2 or later, so we will use UNITY_VERSION instead
|
|
// https://github.com/Cyanilux/URP_ShaderCodeTemplates/blob/main/URP_SimpleLitTemplate.shader#L145
|
|
#if UNITY_VERSION >= 202220 // (for URP 14 or above)
|
|
float2 uv = input.texcoord; // URP14 changed the naming from uv to texcoord, see URP14's Runtime\Utilities\Blit.hlsl
|
|
#else // (for below URP 14)
|
|
float2 uv = input.uv;
|
|
#endif
|
|
|
|
int index = floor(uv.x * MAX_CHARACTER_COUNT);
|
|
float3 center;
|
|
center.x = _GlobalAverageShadowTestBoundingSphereDataArray[index*4+0];
|
|
center.y = _GlobalAverageShadowTestBoundingSphereDataArray[index*4+1];
|
|
center.z = _GlobalAverageShadowTestBoundingSphereDataArray[index*4+2];
|
|
float radius = _GlobalAverageShadowTestBoundingSphereDataArray[index*4+3];
|
|
|
|
// for any not in use slots, radius should be 0,
|
|
// early exit to improve performance, since usually not much characters are enabled in scene
|
|
if(radius == 0.0) return 1;
|
|
|
|
Light mainLight = GetMainLight();
|
|
|
|
// TODO: [bug] when camera is close to character, shadow will fadeout if shadow cascade is > 1
|
|
|
|
// [Disabled. because enable this will make shadow fadeout too easily when camera is close to character]
|
|
// added to prevent generating shadow due to near by objects
|
|
//center += mainLight.direction; // hardcode 1m, not the best solution
|
|
|
|
// [Disabled. because enable this will make character darken when camera is close to character]
|
|
// added to prevent out of bound
|
|
//radius = min(radius, distance(center,_WorldSpaceCameraPos)-_ProjectionParams.y);
|
|
|
|
// this crazy forloop^3 looks extremely scary,
|
|
// but it will run once per active character only, so it will not affect performance at all
|
|
float shadowTestSum = 0;
|
|
for(int x = -TEST_COUNT ; x < TEST_COUNT ; x++)
|
|
for(int y = -TEST_COUNT ; y < TEST_COUNT ; y++)
|
|
for(int z = -TEST_COUNT ; z < TEST_COUNT ; z++)
|
|
{
|
|
float3 shadowTestPosWS = center + float3(x,y,z) / TEST_COUNT / 2.0 * radius;
|
|
|
|
// copy from LitForwardPass.hlsl -> void InitializeInputData(Varyings input, half3 normalTS, out InputData inputData);
|
|
float4 shadowCoord = TransformWorldToShadowCoord(shadowTestPosWS);
|
|
|
|
// copy from Lighting.hlsl -> half4 UniversalFragmentPBR(InputData inputData, SurfaceData surfaceData);
|
|
float shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
|
|
|
|
shadowTestSum += shadowAttenuation;
|
|
}
|
|
float count1D = TEST_COUNT * 2 + 1;
|
|
shadowTestSum /= float(count1D*count1D*count1D) * 0.25; // 0.25 can be any number. the bigger the number, the more easier to be in shadow
|
|
|
|
return lerp(1,saturate(shadowTestSum),_GlobalAverageShadowStrength);
|
|
}
|
|
|
|
ENDHLSL
|
|
|
|
SubShader
|
|
{
|
|
ZTest Always ZWrite Off Cull Off
|
|
|
|
Pass
|
|
{
|
|
Name "RenderAverageShadowTestRT"
|
|
|
|
HLSLPROGRAM
|
|
#pragma vertex Vert // FullscreenVert
|
|
#pragma fragment Frag
|
|
ENDHLSL
|
|
}
|
|
}
|
|
} |