Shader code cleanup;

Added punctual light evaluation in light loop;
This commit is contained in:
Misaki
2025-01-27 17:54:19 +09:00
parent fac66d8694
commit 1a82022a6f
9 changed files with 278 additions and 83 deletions

View File

@@ -4,9 +4,8 @@
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/PhysicalCamera.hlsl"
#include "Packages/com.misaki.hdrp-toon/Runtime/HDRP/Shaders/Includes/Common/UtsPBR.hlsl"
#include "Packages/com.misaki.hdrp-toon/Runtime/HDRP/Shaders/Includes/Common/UtsMaterialEvaluation.hlsl"
#include "Packages/com.misaki.hdrp-toon/Runtime/HDRP/Shaders/Includes/Lighting/UtsLightEvaluation.hlsl"
#include "Packages/com.misaki.hdrp-toon/Runtime/HDRP/Shaders/Includes/Lighting/UtsEnvLight.hlsl"
// Channel mask enum.
// this must be same to UI cs code
@@ -49,7 +48,7 @@ int GetUtsMainLightIndex(BuiltinData builtinData)
if (IsMatchingLightLayer(_DirectionalLightDatas[i].lightLayers, builtinData.renderingLayers))
{
float3 currentLightColor = _DirectionalLightDatas[i].color;
float currentLightAttenuation = GetLightAttenuation(currentLightColor);
float currentLightAttenuation = GetColorAttenuation(currentLightColor);
if (mainLightIndex == -1 || (currentLightAttenuation > lightAttenuation))
{
@@ -82,11 +81,6 @@ bool UtsUseScreenSpaceShadow(DirectionalLightData light, float3 normalWS)
void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bsdfData, BuiltinData builtinData,
float3 V, uint featureFlags, out LightLoopOutput lightLoopOutput)
{
AggregateLighting aggregateLighting;
ZERO_INITIALIZE(AggregateLighting, aggregateLighting);
PreLightData preLightData = GetPreLightData_UTS(V, posInput, bsdfData);
LightLoopContext context;
context.shadowContext = InitShadowContext();
context.shadowValue = 1;
@@ -106,13 +100,13 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
{
DirectionalLightData light = _DirectionalLightDatas[_DirectionalShadowIndex];
#if defined(SCREEN_SPACE_SHADOWS_ON) && !defined(_SURFACE_TYPE_TRANSPARENT)
#if defined(SCREEN_SPACE_SHADOWS_ON) && !defined(_SURFACE_TYPE_TRANSPARENT)
if (UseScreenSpaceShadow(light, bsdfData.normalWS))
{
context.shadowValue = GetScreenSpaceColorShadow(posInput, light.screenSpaceShadowIndex).SHADOW_TYPE_SWIZZLE;
}
else
#endif
#endif
{
float3 L = -light.forward;
@@ -128,6 +122,81 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
}
}
PreLightData preLightData = GetPreLightData_UTS(V, posInput, bsdfData);
AggregateLighting aggregateLighting;
ZERO_INITIALIZE(AggregateLighting, aggregateLighting);
// Evaluate the punctual lights.
if (featureFlags & LIGHTFEATUREFLAGS_PUNCTUAL)
{
uint lightCount, lightStart;
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, lightStart, lightCount);
#else // LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
lightCount = _PunctualLightCount;
lightStart = 0;
#endif
bool fastPath = false;
#if SCALARIZE_LIGHT_LOOP
uint lightStartLane0;
fastPath = IsFastPath(lightStart, lightStartLane0);
if (fastPath)
{
lightStart = lightStartLane0;
}
#endif
// Scalarized loop. All lights that are in a tile/cluster touched by any pixel in the wave are loaded (scalar load), only the one relevant to current thread/pixel are processed.
// For clarity, the following code will follow the convention: variables starting with s_ are meant to be wave uniform (meant for scalar register),
// v_ are variables that might have different value for each thread in the wave (meant for vector registers).
// This will perform more loads than it is supposed to, however, the benefits should offset the downside, especially given that light data accessed should be largely coherent.
// Note that the above is valid only if wave intriniscs are supported.
uint v_lightListOffset = 0;
uint v_lightIdx = lightStart;
#if NEED_TO_CHECK_HELPER_LANE
// On some platform helper lanes don't behave as we'd expect, therefore we prevent them from entering the loop altogether.
// IMPORTANT! This has implications if ddx/ddy is used on results derived from lighting, however given Lightloop is called in compute we should be
// sure it will not happen.
bool isHelperLane = WaveIsHelperLane();
while (!isHelperLane && v_lightListOffset < lightCount)
#else
while (v_lightListOffset < lightCount)
#endif
{
v_lightIdx = FetchIndex(lightStart, v_lightListOffset);
#if SCALARIZE_LIGHT_LOOP
uint s_lightIdx = ScalarizeElementIndex(v_lightIdx, fastPath);
#else
uint s_lightIdx = v_lightIdx;
#endif
if (s_lightIdx == -1)
{
break;
}
LightData s_lightData = FetchLight(s_lightIdx);
// If current scalar and vector light index match, we process the light. The v_lightListOffset for current thread is increased.
// Note that the following should really be ==, however, since helper lanes are not considered by WaveActiveMin, such helper lanes could
// end up with a unique v_lightIdx value that is smaller than s_lightIdx hence being stuck in a loop. All the active lanes will not have this problem.
if (s_lightIdx >= v_lightIdx)
{
v_lightListOffset++;
if (IsMatchingLightLayer(s_lightData.lightLayers, builtinData.renderingLayers))
{
DirectLighting lighting = UtsEvaluateBSDF_Punctual(context, posInput, builtinData, s_lightData, bsdfData, preLightData, V, fragInputs.texCoord0.xy);
AccumulateDirectLighting(lighting, aggregateLighting);
}
}
}
}
// Evaluate the directional lights.
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
{
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
@@ -135,12 +204,13 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
{
if (IsMatchingLightLayer(_DirectionalLightDatas[i].lightLayers, builtinData.renderingLayers))
{
DirectLighting direct = UtsEvaluateShading_Directional(context, posInput, builtinData, _DirectionalLightDatas[i], bsdfData, preLightData, V);
DirectLighting direct = UtsEvaluateBSDF_Directional(context, posInput, builtinData, _DirectionalLightDatas[i], bsdfData, preLightData, V, fragInputs.texCoord0.xy);
AccumulateDirectLighting(direct, aggregateLighting);
}
}
}
// Evaluate the environment lights.
if (featureFlags & (LIGHTFEATUREFLAGS_ENV | LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_SSREFRACTION | LIGHTFEATUREFLAGS_SSREFLECTION))
{
float reflectionHierarchyWeight = 0.0; // Max: 1.0
@@ -148,18 +218,18 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
uint envLightStart, envLightCount;
// Fetch first env light to provide the scene proxy for screen space computation
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
#ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
GetCountAndStart(posInput, LIGHTCATEGORY_ENV, envLightStart, envLightCount);
#else // LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
#else
envLightCount = _EnvLightCount;
envLightStart = 0;
#endif
#endif
bool fastPath = false;
#if SCALARIZE_LIGHT_LOOP
uint envStartFirstLane;
fastPath = IsFastPath(envLightStart, envStartFirstLane);
#endif
#if SCALARIZE_LIGHT_LOOP
uint envStartFirstLane;
fastPath = IsFastPath(envLightStart, envStartFirstLane);
#endif
// Reflection hierarchy is
// 1. Screen Space Reflection