Skip to content

Commit f4171d5

Browse files
AndrewSaraevUnitypastasfuture
authored andcommitted
Dynamic GI:
Dynamic GI sky lighting (#53) * Sample sky lighting on the edges of Probe Volumes for dynamic GI propagation. * Added Sky Contribution setting to Probe Dynamic GI volume component. * Renamed "Sky Contribution" to "Sky Multiplier" to fit better with "Baked Emission Multiplier". * Removed the Direct Contribution setting and normalization that led to all bounces being effectively multiplied by 0.5 with default settings. * Rotate axes in ProbePropagationCombine in the way consistent with other stages. * Added Max Albedo setting for dynamic GI to prevent infinite bounces from blowing up the lighting. * Apply validity to emission. Cleanup. * Changed default Max Albedo to 0.9. * Divide dynamic GI direct lighting by Pi to fix the look. * Experimental changes to skylight and direct hit injection before looking deeper into our SG-to-SH conversion. * Replaced weight normalization in hit and miss passes with prenormalized amplitudes. Experimental. * Added the inv-pi normalization to infinite bounces. * Finish fixing up normalization of hits, misses, and sky. Additionally, add amplitude adjustment for edge and diagonal SGs * Fixed StackLit shader graphs compilation by adding missing ComputeReflectionProbeNormalizationDirection function, expected by the LightLoop. * WIP Dynamic GI bases: Windowed Spherical Gaussian and Ambient Dice * Turn back on sky contribution * More iteration * Latest * Cleanup dynamic gi propagation bases defines into their own header that exposes an api so that callers do not have to know the specifics of the basis. Expose all bases as options on the Probe Dynamic GI volume override * Miss integral * Fix hit and miss lobe creation to the more subtle, but correct implementation that got lost during the cleanup. * Formalize the logic for injecting light from neighboring probe volumes / sky into a basis axis. Convolve the incoming irradiance with the zonal harmonic representation of the neighbor basis lobe in order to analytically evaluate the incoming irradiance over the entire lobe, rather than just the point sample. I compared this against a brute force monte carlo sampling of the SH over the neighbor axis lobe and the results are almost completely indestringuishable. The accuracy is based on how accurate the ZH fit of the neighbor axis lobe is. * remove some dead code * delete more dead code * Add back a line of code I accidentally deleted in the cleanup * Split up the basis options into a basis dropdown and a basis propagation override dropdown. Removed the not useful no diagonal basis options. Added ambient dice wrapped options to the propagation override modes * Remove old option for SH from SG Mode: We now always use the correct SH From SG via zonal harmonic fit conversion. Changed the default propagation override to Basis Ambient Dice Wrapped Super Soft. Fixed a subtle bug with skylight propagation - use the current axis lobe direction for sampling the sky, not the neighbor direction. This makes it consistent with how hits are propagated (and cleans up a little code in the process) Co-authored-by: pastasfuture <[email protected]> Dynamic GI: Dynamic GI: Fixed Dynamic GI and the neighborhood debug draw when there are 0 hits in a volume (no geometry was hit). Renormalize axes of Dynamic GI bases to support different quality (#61) * Added frame settings for Dynamic GI quality to be able to preview it in edit mode. * Precalculate and normalize axis weights on CPU.
1 parent 8e2caa0 commit f4171d5

27 files changed

+1405
-420
lines changed

com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/FrameSettingsUI.Drawers.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,11 +338,27 @@ static void Drawer_SectionLightingSettings(SerializedFrameSettings serialized, E
338338
hasMixedValues: serialized.sssCustomSampleBudget.hasMultipleDifferentValues
339339
);
340340

341+
// Probe Volumes
342+
area.AmmendInfo(FrameSettingsField.ProbeVolume, overrideable: () => hdrpSettings.supportProbeVolume);
343+
area.AmmendInfo(FrameSettingsField.NormalizeReflectionProbeWithProbeVolume, overrideable: () => hdrpSettings.supportProbeVolume);
344+
area.AmmendInfo(FrameSettingsField.ProbeVolumeDynamicGI, overrideable: () => hdrpSettings.supportProbeVolume && hdrpSettings.supportProbeVolumeDynamicGI);
345+
area.AmmendInfo(FrameSettingsField.ProbeVolumeDynamicGIInfiniteBounces, overrideable: () => hdrpSettings.supportProbeVolume && hdrpSettings.supportProbeVolumeDynamicGI);
346+
area.AmmendInfo(FrameSettingsField.ProbeVolumeDynamicGIPropagationQuality,
347+
customGetter: () => (ScalableLevel3ForFrameSettingsUIOnly)serialized.probeVolumeDynamicGIPropagationQuality.intValue, // 3 levels
348+
customSetter: v => serialized.probeVolumeDynamicGIPropagationQuality.intValue = Math.Max(0, Math.Min((int)v, 2)), // Levels 0-2
349+
hasMixedValues: serialized.probeVolumeDynamicGIPropagationQuality.hasMultipleDifferentValues,
350+
overrideable: () => hdrpSettings.supportProbeVolume && hdrpSettings.supportProbeVolumeDynamicGI
351+
);
352+
area.AmmendInfo(FrameSettingsField.ProbeVolumeDynamicGIMaxSimulationsPerFrame,
353+
customGetter: () => serialized.probeVolumeDynamicGIMaxSimulationsPerFrame.intValue,
354+
customSetter: v => serialized.probeVolumeDynamicGIMaxSimulationsPerFrame.intValue = Math.Max(-1, Math.Min((int)v, 128)),
355+
hasMixedValues: serialized.probeVolumeDynamicGIMaxSimulationsPerFrame.hasMultipleDifferentValues,
356+
overrideable: () => hdrpSettings.supportProbeVolume && hdrpSettings.supportProbeVolumeDynamicGI
357+
);
358+
341359
area.AmmendInfo(FrameSettingsField.Volumetrics, overrideable: () => hdrpSettings.supportVolumetrics);
342360
area.AmmendInfo(FrameSettingsField.ReprojectionForVolumetrics, overrideable: () => hdrpSettings.supportVolumetrics);
343361
area.AmmendInfo(FrameSettingsField.LightLayers, overrideable: () => hdrpSettings.supportLightLayers);
344-
area.AmmendInfo(FrameSettingsField.ProbeVolume, overrideable: () => hdrpSettings.supportProbeVolume);
345-
area.AmmendInfo(FrameSettingsField.ProbeVolumeDynamicGI, overrideable: () => hdrpSettings.supportProbeVolumeDynamicGI);
346362
area.AmmendInfo(FrameSettingsField.ScreenSpaceShadows, overrideable: () => hdrpSettings.hdShadowInitParams.supportScreenSpaceShadows);
347363
area.AmmendInfo(FrameSettingsField.HierarchicalVarianceScreenSpaceShadows, overrideable: () => hdrpSettings.hdShadowInitParams.supportHierarchicalVarianceScreenSpaceShadows);
348364
area.Draw(withOverride);

com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedFrameSettings.cs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ class SerializedFrameSettings
2020
public SerializedProperty maximumLODLevel;
2121
public SerializedProperty maximumLODLevelMode;
2222
public SerializedProperty maximumLODLevelQualityLevel;
23+
public SerializedProperty probeVolumeDynamicGIPropagationQuality;
24+
public SerializedProperty probeVolumeDynamicGIMaxSimulationsPerFrame;
2325
public SerializedProperty materialQuality;
2426

2527
public SerializedObject serializedObject => m_RootData.serializedObject;
@@ -91,16 +93,18 @@ public SerializedFrameSettings(SerializedProperty rootData, SerializedProperty r
9193
m_BitDatas = rootData.FindPropertyRelative("bitDatas").ToSerializeBitArray128();
9294
m_BitOverrides = rootOverrides?.FindPropertyRelative("mask").ToSerializeBitArray128(); //rootOverride can be null in case of hdrpAsset defaults
9395

94-
sssQualityMode = rootData.FindPropertyRelative("sssQualityMode");
95-
sssQualityLevel = rootData.FindPropertyRelative("sssQualityLevel");
96-
sssCustomSampleBudget = rootData.FindPropertyRelative("sssCustomSampleBudget");
97-
lodBias = rootData.FindPropertyRelative("lodBias");
98-
lodBiasMode = rootData.FindPropertyRelative("lodBiasMode");
99-
lodBiasQualityLevel = rootData.FindPropertyRelative("lodBiasQualityLevel");
100-
maximumLODLevel = rootData.FindPropertyRelative("maximumLODLevel");
101-
maximumLODLevelMode = rootData.FindPropertyRelative("maximumLODLevelMode");
102-
maximumLODLevelQualityLevel = rootData.FindPropertyRelative("maximumLODLevelQualityLevel");
103-
materialQuality = rootData.Find((FrameSettings s) => s.materialQuality);
96+
sssQualityMode = rootData.FindPropertyRelative("sssQualityMode");
97+
sssQualityLevel = rootData.FindPropertyRelative("sssQualityLevel");
98+
sssCustomSampleBudget = rootData.FindPropertyRelative("sssCustomSampleBudget");
99+
lodBias = rootData.FindPropertyRelative("lodBias");
100+
lodBiasMode = rootData.FindPropertyRelative("lodBiasMode");
101+
lodBiasQualityLevel = rootData.FindPropertyRelative("lodBiasQualityLevel");
102+
maximumLODLevel = rootData.FindPropertyRelative("maximumLODLevel");
103+
maximumLODLevelMode = rootData.FindPropertyRelative("maximumLODLevelMode");
104+
maximumLODLevelQualityLevel = rootData.FindPropertyRelative("maximumLODLevelQualityLevel");
105+
probeVolumeDynamicGIPropagationQuality = rootData.FindPropertyRelative("probeVolumeDynamicGIPropagationQuality");
106+
probeVolumeDynamicGIMaxSimulationsPerFrame = rootData.FindPropertyRelative("probeVolumeDynamicGIMaxSimulationsPerFrame");
107+
materialQuality = rootData.Find((FrameSettings s) => s.materialQuality);
104108
}
105109

106110
public struct TitleDrawingScope : IDisposable
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#ifndef AMBIENT_DICE
2+
#define AMBIENT_DICE
3+
4+
struct AmbientDice
5+
{
6+
float amplitude;
7+
float sharpness;
8+
float3 mean;
9+
};
10+
11+
float AmbientDiceEvaluateFromDirection(in AmbientDice a, const in float3 direction)
12+
{
13+
return a.amplitude * pow(saturate(dot(a.mean, direction)), a.sharpness);
14+
}
15+
16+
struct AmbientDiceWrapped
17+
{
18+
float amplitude;
19+
float sharpness;
20+
float3 mean;
21+
};
22+
23+
float AmbientDiceWrappedEvaluateFromDirection(in AmbientDiceWrapped a, const in float3 direction)
24+
{
25+
return a.amplitude * pow(saturate(dot(a.mean, direction) * 0.5 + 0.5), a.sharpness);
26+
}
27+
28+
// Analytic function fit over the sharpness range of [2, 32]
29+
// https://www.desmos.com/calculator/gl9lomqucs
30+
float AmbientDiceIntegralFromSharpness(const in float sharpness)
31+
{
32+
return exp2(6.14741 * pow(abs(sharpness * 12.5654 + 14.6469), -1.0)) * 18.5256 + -18.5238;
33+
}
34+
35+
float AmbientDiceIntegral(const in AmbientDice a)
36+
{
37+
return a.amplitude * AmbientDiceIntegralFromSharpness(a.sharpness);
38+
}
39+
40+
// Does not include divide by PI required to normalize the clamped cosine diffuse BRDF.
41+
// This was done to match the format of SGIrradianceFitted() which also does not include the divide by PI.
42+
// Post dividing by PI is required.
43+
float AmbientDiceAndClampedCosineProductIntegral(const in AmbientDice a, const in float3 clampedCosineNormal)
44+
{
45+
float mDotN = dot(a.mean, clampedCosineNormal);
46+
47+
float sharpnessScale = pow(abs(a.sharpness), -0.121796) * -2.18362 + 2.7562;
48+
float sharpnessBias = pow(abs(a.sharpness), 0.137288) * -0.555517 + 0.711175;
49+
50+
mDotN = mDotN * sharpnessScale + sharpnessBias;
51+
52+
float res = max(0.0, exp2(-9.45649 * pow(abs(mDotN * 0.240416 + 1.16513), -5.16291)) * 2.71745 + -0.00193676);
53+
res *= AmbientDiceIntegral(a);
54+
return res;
55+
}
56+
57+
// https://www.desmos.com/calculator/umjtgtzmk8
58+
// Fit to pre-deringed data.
59+
// The dering constraint is evaluated post diffuse brdf convolution.
60+
// The signal can still ring in raw irradiance space.
61+
float ComputeZonalHarmonicC0FromAmbientDiceSharpness(float sharpness)
62+
{
63+
return pow(abs(sharpness * 1.62301 + 1.59682), -0.993255) * 2.83522 + -0.001;
64+
}
65+
66+
float ComputeZonalHarmonicC1FromAmbientDiceSharpness(float sharpness)
67+
{
68+
return exp2(3.37607 * pow(abs(sharpness * 1.45269 + 6.46623), -1.88874)) * 20.0 + -19.9337;
69+
}
70+
71+
72+
float ComputeZonalHarmonicC2FromAmbientDiceSharpness(float sharpness)
73+
{
74+
float lhs = 0.239989 + 0.42846 * sharpness + -0.202951 * sharpness * sharpness + 0.0303908 * sharpness * sharpness * sharpness;
75+
float rhs = exp2(-1.44747 * pow(abs(sharpness * 0.644014 + -0.188877), -0.94422)) * -0.970862 + 0.967661;
76+
return sharpness > 2.33 ? rhs : lhs;
77+
}
78+
79+
float3 ComputeZonalHarmonicFromAmbientDiceSharpness(float sharpness)
80+
{
81+
return float3(
82+
ComputeZonalHarmonicC0FromAmbientDiceSharpness(sharpness),
83+
ComputeZonalHarmonicC1FromAmbientDiceSharpness(sharpness),
84+
ComputeZonalHarmonicC2FromAmbientDiceSharpness(sharpness)
85+
);
86+
}
87+
88+
#endif
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/DynamicGI/ProbeDynamicGI.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,28 @@ public class ProbeDynamicGI : VolumeComponent
2121
public ClampedFloatParameter indirectMultiplier = new ClampedFloatParameter(1f, 0.0f, 2f);
2222
[Tooltip("Multiplier for material emissive colors that affect Dynamic GI")]
2323
public ClampedFloatParameter bakedEmissionMultiplier = new ClampedFloatParameter(0f, 0f, 2f);
24+
[Tooltip("Multiplier for sky lighting that affect Dynamic GI of")]
25+
public ClampedFloatParameter skyMultiplier = new ClampedFloatParameter(0f, 0f, 2f);
2426
[Tooltip("A control for blending in more influence of infinite bounce light near surfaces")]
2527
public ClampedFloatParameter infiniteBounce = new ClampedFloatParameter(1f, 0.0f, 2f);
28+
[Tooltip("Limits albedo value used for infinite bounces to prevent lighting from blowing up")]
29+
public ClampedFloatParameter maxAlbedo = new ClampedFloatParameter(0.9f, 0f, 1f);
30+
[Tooltip("Advanced control for the contribution amount of secondary propagation indirect light")]
31+
public ClampedFloatParameter propagationContribution = new ClampedFloatParameter(1f, 0f, 2f);
2632

2733
[Tooltip("Max range to perform dynamic GI operation on an individual probe")]
2834
public ClampedFloatParameter rangeInFrontOfCamera = new ClampedFloatParameter(50.0f, 0.0f, 100.0f);
2935
[Tooltip("Max range to perform dynamic GI operation on an individual probe")]
3036
public ClampedFloatParameter rangeBehindCamera = new ClampedFloatParameter(25.0f, 0.0f, 100.0f);
3137

32-
[Tooltip("Advanced control for the contribution amount of direct light")]
33-
public ClampedFloatParameter directContribution = new ClampedFloatParameter(1f, 0.5f, 2);
34-
[Tooltip("Advanced control for the contribution amount of secondary propagation indirect light")]
35-
public ClampedFloatParameter propagationContribution = new ClampedFloatParameter(1f, 0.5f, 2);
38+
[Tooltip("Advanced control selecting the how light is represented and propagated along each axis")]
39+
public ProbeVolumeDynamicGIBasisParameter basis = new ProbeVolumeDynamicGIBasisParameter(ProbeVolumeDynamicGI.ProbeVolumeDynamicGIBasis.BasisAmbientDiceSharp);
40+
[Tooltip("Advanced control selecting an alternative basis for use during propagation. None uses the same basis for propagation as hits.")]
41+
public ProbeVolumeDynamicGIBasisPropagationOverrideParameter basisPropagationOverride = new ProbeVolumeDynamicGIBasisPropagationOverrideParameter(ProbeVolumeDynamicGI.ProbeVolumeDynamicGIBasisPropagationOverride.BasisAmbientDiceWrappedSuperSoft);
42+
[Tooltip("Advanced control for the SG sharpness used when evaluating the influence of infinite bounce light near surfaces")]
43+
public ClampedFloatParameter sharpness = new ClampedFloatParameter(6.0f, 0.0f, 16.0f);
3644
[Tooltip("Advanced control for the SG sharpness used when propagating light")]
3745
public ClampedFloatParameter propagationSharpness = new ClampedFloatParameter(2.0f, 0.0f, 16.0f);
38-
[Tooltip("Advanced control for the SG sharpness used when evaluating the influence of infinite bounce light near surfaces")]
39-
public ClampedFloatParameter infiniteBounceSharpness = new ClampedFloatParameter(2.0f, 0.0f, 16.0f);
40-
[Tooltip("Advanced control for probe propagation combine pass.\nSamplePeakAndProject: Spherical gaussians will simply be evaluated at their peak and projected to convert to spherical harmonics.\nSHFromSGFit: A spherical gaussian to spherical harmonic function fit is used, which is physically plausible.\nSHFromSGFitWithCosineWindow: A spherical gaussian with an additional cosine window to spherical harmonic function fit is used, which is physically plausible. Less directional blur than SHFromSGFit.")]
41-
public SHFromSGModeParameter shFromSGMode = new SHFromSGModeParameter(SHFromSGMode.SamplePeakAndProject);
4246
[Tooltip("Advanced control for darkening down the indirect light on invalid probes")]
4347
public ClampedFloatParameter leakMultiplier = new ClampedFloatParameter(0.0f, 0.0f, 1.0f);
4448
[Tooltip("Advanced control to bias the distance from the normal of the hit surface to perform direct lighting evaluation on")]
@@ -54,18 +58,18 @@ public class ProbeDynamicGI : VolumeComponent
5458
[Tooltip("Advanced control to clear all dynamic GI buffers in the event lighting blows up when tuning")]
5559
public BoolParameter clear = new BoolParameter(false);
5660

61+
5762
[Serializable]
58-
public enum SHFromSGMode
63+
public sealed class ProbeVolumeDynamicGIBasisParameter : VolumeParameter<ProbeVolumeDynamicGI.ProbeVolumeDynamicGIBasis>
5964
{
60-
SamplePeakAndProject = 0,
61-
SHFromSGFit,
62-
SHFromSGFitWithCosineWindow
63-
};
65+
public ProbeVolumeDynamicGIBasisParameter(ProbeVolumeDynamicGI.ProbeVolumeDynamicGIBasis value, bool overrideState = false)
66+
: base(value, overrideState) {}
67+
}
6468

6569
[Serializable]
66-
public sealed class SHFromSGModeParameter : VolumeParameter<SHFromSGMode>
70+
public sealed class ProbeVolumeDynamicGIBasisPropagationOverrideParameter : VolumeParameter<ProbeVolumeDynamicGI.ProbeVolumeDynamicGIBasisPropagationOverride>
6771
{
68-
public SHFromSGModeParameter(SHFromSGMode value, bool overrideState = false)
72+
public ProbeVolumeDynamicGIBasisPropagationOverrideParameter(ProbeVolumeDynamicGI.ProbeVolumeDynamicGIBasisPropagationOverride value, bool overrideState = false)
6973
: base(value, overrideState) {}
7074
}
7175

com.unity.render-pipelines.high-definition/Runtime/Lighting/ProbeVolume/DynamicGI/ProbePropagation.hlsl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,19 @@ float3 ReadPreviousPropagationAxis(uint probeIndex, uint axisIndex)
3131
return _PreviousRadianceCacheAxis[index];
3232
}
3333

34-
float3 NormalizeOutputRadiance(float4 lightingAndWeight, float probeValidity)
34+
float3 NormalizeOutputRadiance(float3 lighting, float probeValidity)
3535
{
3636
float validity = pow(1.0 - probeValidity, 8.0);
3737
const float invalidScale = (1.0f - lerp(_LeakMultiplier, 0.0f, validity));
3838

39-
float3 radiance = lightingAndWeight.xyz * invalidScale;
40-
radiance *= rcp(lightingAndWeight.w);
39+
float3 radiance = lighting * invalidScale;
4140

4241
return radiance;
4342
}
4443

45-
void WritePropagationOutput(uint index, float4 lightingAndWeight, float probeValidity)
44+
void WritePropagationOutput(uint index, float3 lighting, float probeValidity)
4645
{
47-
const float3 finalRadiance = NormalizeOutputRadiance(lightingAndWeight, probeValidity);
46+
const float3 finalRadiance = NormalizeOutputRadiance(lighting, probeValidity);
4847
_RadianceCacheAxis[index] = finalRadiance;
4948
}
5049

0 commit comments

Comments
 (0)