HTrace WSGI composites indirect lighting after post-processing using the GBuffer albedo/occlusion of the player's stock URP GBuffer pass. That pass knew neither the painted-height AO semantics nor the brightness/saturation grade, so desaturated paint reappeared fully saturated in shadow/indirect light and painted height modulated GI with the raw 0.5-centered value. - PlayerCamoShared.hlsl (new): single source for camo knobs, ApplyPaintedHeightSurface and ApplyCamoBodyGrade shared by both passes - PlayerCamoGBuffer.hlsl (new): CamoGBufferFragment = URP 17.3 Lit GBuffer fragment + height-AO remap on occlusion + grade applied to albedo - PlayerCamoLit.shader: GBuffer pass now uses CamoGBufferFragment - PlayerCamo.hlsl: consumes the shared helpers (forward path unchanged) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
3.3 KiB
HLSL
72 lines
3.3 KiB
HLSL
#ifndef PLAYER_CAMO_GBUFFER_INCLUDED
|
|
#define PLAYER_CAMO_GBUFFER_INCLUDED
|
|
|
|
// Camo variant of URP's LitGBufferPassFragment. Include AFTER LitGBufferPass.hlsl (reuses its
|
|
// Varyings / InitializeInputData / InitializeBakedGIData).
|
|
//
|
|
// The project renders FORWARD, so this GBuffer pass has exactly ONE consumer: HTrace WSGI renders
|
|
// its thin GBuffer through the "UniversalGBuffer" tag and its GI composite multiplies the traced
|
|
// irradiance by GBuffer0.rgb (diffuse albedo) and GBuffer1.a (occlusion), ADDING the result after
|
|
// post-processing - i.e. after the forward pass's camo grade already ran. Two camo hooks keep that
|
|
// injected indirect light consistent with the graded forward look:
|
|
// 1. ApplyPaintedHeightSurface: forward AO semantics for the painted height (neutral 0.5 -> AO 1)
|
|
// instead of the raw 0.5-centred height value in GBuffer1.a, + the relief normal.
|
|
// 2. ApplyCamoBodyGrade on the albedo: brightness/saturation follow into the injected GI, so
|
|
// desaturated paint stays desaturated in shadows / under indirect light.
|
|
// Everything else is a faithful copy of URP 17.3 LitGBufferPass.hlsl's fragment.
|
|
|
|
#include "PlayerCamoShared.hlsl"
|
|
|
|
GBufferFragOutput CamoGBufferFragment(Varyings input)
|
|
{
|
|
UNITY_SETUP_INSTANCE_ID(input);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
|
|
|
|
#if defined(_PARALLAXMAP)
|
|
#if defined(REQUIRES_TANGENT_SPACE_VIEW_DIR_INTERPOLATOR)
|
|
half3 viewDirTS = input.viewDirTS;
|
|
#else
|
|
half3 viewDirWS = GetWorldSpaceNormalizeViewDir(input.positionWS);
|
|
half3 viewDirTS = GetViewDirectionTangentSpace(input.tangentWS, input.normalWS, viewDirWS);
|
|
#endif
|
|
ApplyPerPixelDisplacement(viewDirTS, input.uv);
|
|
#endif
|
|
|
|
SurfaceData surfaceData;
|
|
InitializeStandardLitSurfaceData(input.uv, surfaceData);
|
|
|
|
// Camo hooks (see header). The albedo grade is clamped: GBuffer0 is UNORM, and HTrace multiplies
|
|
// its GI by the stored value, so out-of-range brightness would clip there anyway.
|
|
ApplyPaintedHeightSurface(input.uv, surfaceData);
|
|
ApplyCamoBodyGrade(surfaceData.albedo);
|
|
surfaceData.albedo = saturate(surfaceData.albedo);
|
|
|
|
#ifdef LOD_FADE_CROSSFADE
|
|
LODFadeCrossFade(input.positionCS);
|
|
#endif
|
|
|
|
InputData inputData;
|
|
InitializeInputData(input, surfaceData.normalTS, inputData);
|
|
SETUP_DEBUG_TEXTURE_DATA(inputData, UNDO_TRANSFORM_TEX(input.uv, _BaseMap));
|
|
|
|
#if defined(_DBUFFER)
|
|
ApplyDecalToSurfaceData(input.positionCS, surfaceData, inputData);
|
|
#endif
|
|
|
|
InitializeBakedGIData(input, inputData);
|
|
|
|
BRDFData brdfData;
|
|
InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData);
|
|
|
|
Light mainLight = GetMainLight(inputData.shadowCoord, inputData.positionWS, inputData.shadowMask);
|
|
MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, inputData.shadowMask);
|
|
|
|
half3 color = GlobalIllumination(brdfData, (BRDFData)0, 0,
|
|
inputData.bakedGI, surfaceData.occlusion, inputData.positionWS,
|
|
inputData.normalWS, inputData.viewDirectionWS, inputData.normalizedScreenSpaceUV);
|
|
|
|
return PackGBuffersBRDFData(brdfData, inputData, surfaceData.smoothness, surfaceData.emission + color, surfaceData.occlusion);
|
|
}
|
|
|
|
#endif
|