Shader code cleanup;
Added punctual light evaluation in light loop;
This commit is contained in:
@@ -9,7 +9,9 @@
|
||||
#define SATURATE_BASE_COLOR_IF_SDR(x) saturate(x)
|
||||
#endif
|
||||
|
||||
#define APPLY_WEIGHT(x, y, t) lerp(x, x * y, t)
|
||||
const float rateR = 0.299;
|
||||
const float rateG = 0.587;
|
||||
const float rateB = 0.114;
|
||||
|
||||
struct UTSLightData
|
||||
{
|
||||
@@ -22,7 +24,7 @@ struct UTSLightData
|
||||
SHADOW_TYPE shadowValue;
|
||||
};
|
||||
|
||||
float GetLightAttenuation(float3 lightColor)
|
||||
float GetColorAttenuation(float3 lightColor)
|
||||
{
|
||||
float lightAttenuation = rateR * lightColor.r + rateG * lightColor.g + rateB * lightColor.b;
|
||||
return lightAttenuation;
|
||||
@@ -36,41 +38,58 @@ float3 GetLimitedLightColor(float3 lightColor)
|
||||
return result;
|
||||
}
|
||||
|
||||
DirectLighting UtsEvaluateShading_Directional(LightLoopContext lightLoopContext, PositionInputs posInput, BuiltinData builtinData, DirectionalLightData lightData, UtsBSDFData bsdfData, PreLightData preLightData, float3 V)
|
||||
DirectLighting UtsEvaluateBSDF_Directional(LightLoopContext lightLoopContext, PositionInputs posInput, BuiltinData builtinData, DirectionalLightData lightData, UtsBSDFData bsdfData, PreLightData preLightData, float3 V, float2 uv0)
|
||||
{
|
||||
DirectLighting lighting;
|
||||
ZERO_INITIALIZE(DirectLighting, lighting);
|
||||
|
||||
float3 L = -lightData.forward;
|
||||
float NdotL = dot(bsdfData.normalWS, L);
|
||||
float halfLambert = 0.5 * NdotL + 0.5;
|
||||
|
||||
SHADOW_TYPE shadow = EvaluateShadow_Directional(lightLoopContext, posInput, lightData, builtinData, bsdfData.normalWS);
|
||||
float systemShadows = saturate(shadow + 0.5f + _Tweak_SystemShadowsLevel > 0.0 ? shadow + 0.5f + _Tweak_SystemShadowsLevel : 0.0);
|
||||
float shadingGrade = lerp(halfLambert, halfLambert * systemShadows, _Set_SystemShadowsToBase);
|
||||
float firstColorFeatherForMask = lerp(_1st_ShadeColor_Feather, 0.0f, max(_ComposerMaskMode, _FirstShadeOverridden));
|
||||
SHADOW_TYPE shadow = EvaluateShadow_Directional(lightLoopContext, posInput, lightData, builtinData, bsdfData.geomNormalWS);
|
||||
|
||||
float finalShadow = saturate((shadingGrade - (_1st_ShadeColor_Step - firstColorFeatherForMask)) / (_1st_ShadeColor_Step - (_1st_ShadeColor_Step - firstColorFeatherForMask))); // Base and 1st Shade Mask
|
||||
|
||||
if (lightData.diffuseDimmer > 0.0 && finalShadow > 0.0)
|
||||
if (lightData.lightDimmer > 0.0)
|
||||
{
|
||||
float secondColorFeatherForMask = lerp(_2nd_ShadeColor_Feather, 0.0f, max(_SecondShadeOverridden, _ComposerMaskMode));
|
||||
float shadeShadow = saturate((halfLambert - (_ShadeColor_Step - secondColorFeatherForMask)) / (_ShadeColor_Step - (_ShadeColor_Step - secondColorFeatherForMask))); // 1st and 2nd Shades Mask
|
||||
|
||||
float3 diffuseTerm = lerp(lerp(bsdfData.secondShadingDiffuseColor, bsdfData.firstShadingDiffuseColor, shadeShadow), bsdfData.diffuseColor, finalShadow);
|
||||
float3 specularTerm = ComputeSpecularTerm(bsdfData, preLightData, V, L) * finalShadow;
|
||||
|
||||
// TODO: Colored shadow will overwrite the first and second shading diffuse color
|
||||
//float3 shadowColor = ComputeShadowColor(shadow, lightData.shadowTint, lightData.penumbraTint);
|
||||
float4 lightColor = EvaluateLight_Directional(lightLoopContext, posInput, lightData);
|
||||
lightColor.rgb *= ComputeShadowColor(systemShadows, lightData.shadowTint, lightData.penumbraTint) * lightColor.a * _Light_Intensity_Multiplier;
|
||||
lightColor.rgb = GetLimitedLightColor(lightColor.rgb);
|
||||
lightColor.rgb = GetLimitedLightColor(lightColor.rgb * lightColor.a * _Light_Intensity_Multiplier);
|
||||
|
||||
lighting.diffuse = diffuseTerm * lightColor.rgb * lightData.diffuseDimmer;
|
||||
lighting.specular += specularTerm * lightColor.rgb * lightData.specularDimmer;
|
||||
UtsClampRoughness(preLightData, bsdfData, lightData.minRoughness);
|
||||
|
||||
lighting = UtsShadeSurface(bsdfData, preLightData, shadow, lightColor.rgb, V, L, uv0, lightData.diffuseDimmer, lightData.specularDimmer);
|
||||
}
|
||||
|
||||
return lighting;
|
||||
}
|
||||
|
||||
DirectLighting UtsEvaluateBSDF_Punctual(LightLoopContext lightLoopContext, PositionInputs posInput, BuiltinData builtinData, LightData lightData, UtsBSDFData bsdfData, PreLightData preLightData, float3 V, float2 uv0)
|
||||
{
|
||||
DirectLighting lighting;
|
||||
ZERO_INITIALIZE(DirectLighting, lighting);
|
||||
|
||||
float3 L;
|
||||
float4 distances; // {d, d^2, 1/d, d_proj}
|
||||
GetPunctualLightVectors(posInput.positionWS, lightData, L, distances);
|
||||
|
||||
PositionInputs shadowPositionInputs = posInput;
|
||||
shadowPositionInputs.positionWS = posInput.positionWS + L * _ShadowBias;
|
||||
|
||||
SHADOW_TYPE shadow = EvaluateShadow_Punctual(lightLoopContext, shadowPositionInputs, lightData, builtinData, bsdfData.geomNormalWS, L, distances);
|
||||
|
||||
if (lightData.lightDimmer > 0.0)
|
||||
{
|
||||
// TODO: Colored shadow will overwrite the first and second shading diffuse color
|
||||
//float3 shadowColor = ComputeShadowColor(shadow, lightData.shadowTint, lightData.penumbraTint);
|
||||
float4 lightColor = EvaluateLight_Punctual(lightLoopContext, posInput, lightData, L, distances);
|
||||
lightColor.rgb = GetLimitedLightColor(lightColor.rgb * lightColor.a * _Light_Intensity_Multiplier);
|
||||
|
||||
UtsClampRoughness(preLightData, bsdfData, lightData.minRoughness);
|
||||
|
||||
lighting = UtsShadeSurface(bsdfData, preLightData, shadow, lightColor.rgb, V, L, uv0, lightData.diffuseDimmer, lightData.specularDimmer);
|
||||
}
|
||||
|
||||
return lighting;
|
||||
}
|
||||
|
||||
IndirectLighting UtsEvaluateBSDF_ScreenSpaceReflection(PositionInputs posInput, PreLightData preLightData, inout float reflectionHierarchyWeight)
|
||||
{
|
||||
IndirectLighting lighting;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user