Add half-res DDGI reflections resolving to optimzie rendering on low-end devices
This commit is contained in:
@@ -37,6 +37,7 @@ void GlobalIlluminationSettings::BlendWith(GlobalIlluminationSettings& other, fl
|
||||
BLEND_COL(FallbackIrradiance);
|
||||
BLEND_ENUM(IndirectResolution);
|
||||
BLEND_ENUM(Reflections);
|
||||
BLEND_ENUM(ReflectionsResolution);
|
||||
}
|
||||
|
||||
void BloomSettings::BlendWith(BloomSettings& other, float weight)
|
||||
|
||||
@@ -365,10 +365,15 @@ API_ENUM(Attributes="Flags") enum class GlobalIlluminationSettingsOverride : int
|
||||
/// </summary>
|
||||
Reflections = 1 << 8,
|
||||
|
||||
/// <summary>
|
||||
/// Overrides <see cref="GlobalIlluminationSettings.ReflectionsResolution"/> property.
|
||||
/// </summary>
|
||||
ReflectionsResolution = 1 << 9,
|
||||
|
||||
/// <summary>
|
||||
/// All properties.
|
||||
/// </summary>
|
||||
All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance | BounceIntensity | IndirectShadowsStrength | IndirectResolution | Reflections,
|
||||
All = Mode | Intensity | TemporalResponse | Distance | FallbackIrradiance | BounceIntensity | IndirectShadowsStrength | IndirectResolution | Reflections | ReflectionsResolution,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -440,6 +445,12 @@ API_STRUCT() struct FLAXENGINE_API GlobalIlluminationSettings : ISerializable
|
||||
API_FIELD(Attributes = "EditorOrder(100), PostProcessSetting((int)GlobalIlluminationSettingsOverride.Reflections)")
|
||||
ReflectionsMode Reflections = ReflectionsMode::EnvironmentProbes;
|
||||
|
||||
/// <summary>
|
||||
/// The indirect specular reflections render resolution. Full gives better quality, but half improves performance.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes = "EditorOrder(110), PostProcessSetting((int)GlobalIlluminationSettingsOverride.ReflectionsResolution)")
|
||||
ResolutionMode ReflectionsResolution = ResolutionMode::Full;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Blends the settings using given weight.
|
||||
|
||||
@@ -75,6 +75,9 @@ GPU_CB_STRUCT(Data0 {
|
||||
float TestValue;
|
||||
Float3 QuantizationError;
|
||||
int32 FrameIndexMod8;
|
||||
Float2 Padding0;
|
||||
float ResolveDitherScaleIndirect;
|
||||
float ResolveDitherScaleSpecular;
|
||||
});
|
||||
|
||||
GPU_CB_STRUCT(Data1 {
|
||||
@@ -182,6 +185,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void InitData0Shared(const RenderContext& renderContext, const DDGICustomBuffer& ddgiData, Data0& data)
|
||||
{
|
||||
data.DDGI = ddgiData.Result.Constants;
|
||||
data.TestValue = Graphics::TestValue;
|
||||
data.TemporalTime = renderContext.List->Setup.UseTemporalAAJitter ? RenderTools::ComputeTemporalTime() : 0.0f;
|
||||
data.FrameIndexMod8 = (int32)(Engine::FrameCount % 8);
|
||||
auto& settings = renderContext.List->Settings.GlobalIllumination;
|
||||
constexpr float DitherScaleHalfRes = 0.1f; // Hardcoded to reduce noise at half-res due to TAA not being able to filter this out (in future BilateralUpscale could try smooth it)
|
||||
data.ResolveDitherScaleIndirect = settings.IndirectResolution == ResolutionMode::Full ? 1.0f : DitherScaleHalfRes;
|
||||
data.ResolveDitherScaleSpecular = settings.ReflectionsResolution == ResolutionMode::Full ? 1.0f : DitherScaleHalfRes;
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
}
|
||||
|
||||
void CalculateVolumeRandomRotation(Matrix3x3& matrix)
|
||||
{
|
||||
// Reference: James Arvo's algorithm Graphics Gems 3 (pages 117-120)
|
||||
@@ -650,7 +666,6 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
||||
Quaternion::RotationMatrix(raysRotationMatrix, raysRotation);
|
||||
raysRotation.Conjugate();
|
||||
|
||||
data.DDGI = ddgiData.Result.Constants;
|
||||
data.GlobalSDF = bindingDataSDF.Constants;
|
||||
data.GlobalSurfaceAtlas = bindingDataSurfaceAtlas.Constants;
|
||||
data.ProbesCount = data.DDGI.ProbesCounts[0] * data.DDGI.ProbesCounts[1] * data.DDGI.ProbesCounts[2];
|
||||
@@ -660,12 +675,10 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
||||
auto& cascade = ddgiData.Cascades[cascadeIndex];
|
||||
data.ProbeScrollClears[cascadeIndex] = Int4(cascade.ProbeScrollClears, 0);
|
||||
}
|
||||
data.TemporalTime = renderContext.List->Setup.UseTemporalAAJitter ? RenderTools::ComputeTemporalTime() : 0.0f;
|
||||
data.ViewDir = renderContext.View.Direction;
|
||||
data.SkyboxIntensity = renderContext.List->Sky ? renderContext.List->Sky->GetIndirectLightingIntensity() : 1.0f;
|
||||
data.TestValue = Graphics::TestValue;
|
||||
data.QuantizationError = RenderTools::GetColorQuantizationError(ddgiData.ProbesIrradiance->Format());
|
||||
data.FrameIndexMod8 = (int32)(Engine::FrameCount % 8);
|
||||
InitData0Shared(renderContext, ddgiData, data);
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
context->UpdateCB(_cb0, &data);
|
||||
context->BindCB(0, _cb0);
|
||||
@@ -899,10 +912,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
if (!render)
|
||||
{
|
||||
Data0 data;
|
||||
data.DDGI = ddgiData->Result.Constants;
|
||||
data.TemporalTime = renderContext.List->Setup.UseTemporalAAJitter ? RenderTools::ComputeTemporalTime() : 0.0f;
|
||||
data.FrameIndexMod8 = (int32)(Engine::FrameCount % 8);
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
InitData0Shared(renderContext, *ddgiData, data);
|
||||
context->UpdateCB(_cb0, &data);
|
||||
context->BindCB(0, _cb0);
|
||||
}
|
||||
@@ -1051,10 +1061,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderReflections(RenderContext& rend
|
||||
if (!render)
|
||||
{
|
||||
Data0 data;
|
||||
data.DDGI = ddgiData->Result.Constants;
|
||||
data.TemporalTime = renderContext.List->Setup.UseTemporalAAJitter ? RenderTools::ComputeTemporalTime() : 0.0f;
|
||||
data.FrameIndexMod8 = (int32)(Engine::FrameCount % 8);
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
InitData0Shared(renderContext, *ddgiData, data);
|
||||
context->UpdateCB(_cb0, &data);
|
||||
context->BindCB(0, _cb0);
|
||||
}
|
||||
@@ -1066,6 +1073,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderReflections(RenderContext& rend
|
||||
context->BindSR(5, ddgiData->Result.ProbesDistance);
|
||||
context->BindSR(6, ddgiData->Result.ProbesRadiance);
|
||||
auto& settings = renderContext.List->Settings.GlobalIllumination;
|
||||
if (settings.ReflectionsResolution == ResolutionMode::Full || !MultiScaler::Instance()->IsReady())
|
||||
{
|
||||
// Full-res
|
||||
auto rtAction = GPUDrawPassAction::Store;
|
||||
@@ -1075,6 +1083,21 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderReflections(RenderContext& rend
|
||||
context->SetState(_psSpecularLighting);
|
||||
context->DrawFullscreenTriangle();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Upscale
|
||||
auto width = RenderTools::GetResolution((int32)renderContext.View.ScreenSize.X, settings.ReflectionsResolution);
|
||||
auto height = RenderTools::GetResolution((int32)renderContext.View.ScreenSize.Y, settings.ReflectionsResolution);
|
||||
auto temp = RenderTargetPool::Get(GPUTextureDescription::New2D(width, height, reflectionsBuffer->GetFormat(), GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget));
|
||||
context->SetViewportAndScissors((float)width, (float)height);
|
||||
context->SetRenderTarget(temp->View());
|
||||
context->SetState(_psSpecularLighting);
|
||||
context->DrawFullscreenTriangle();
|
||||
context->ResetRenderTarget();
|
||||
MultiScaler::Instance()->BilateralUpscale(context, Viewport(Float2(renderContext.View.ScreenSize)), temp, reflectionsBuffer, renderContext.Buffers->DepthBuffer, renderContext.Buffers->GBuffer1);
|
||||
RenderTargetPool::Release(temp);
|
||||
context->SetViewportAndScissors(renderContext.View.ScreenSize.X, renderContext.View.ScreenSize.Y);
|
||||
}
|
||||
context->ResetSR();
|
||||
context->ResetRenderTarget();
|
||||
}
|
||||
|
||||
@@ -52,6 +52,9 @@ float3 ViewDir;
|
||||
float TestValue;
|
||||
float3 QuantizationError;
|
||||
uint FrameIndexMod8;
|
||||
float2 Padding0;
|
||||
float ResolveDitherScaleIndirect;
|
||||
float ResolveDitherScaleSpecular;
|
||||
META_CB_END
|
||||
|
||||
META_CB_BEGIN(1, Data1)
|
||||
@@ -969,7 +972,7 @@ Texture2D<snorm float4> ProbesData : register(t4);
|
||||
Texture2D<float4> ProbesDistance : register(t5);
|
||||
|
||||
// Shared code for both irradiance and specular sampling
|
||||
#define DDGI_GET_DITHER RandN2(input.TexCoord + TemporalTime).x
|
||||
#define DDGI_GET_DITHER (RandN2(input.TexCoord + TemporalTime).x)
|
||||
#define DDGI_GET_SAMPLE_POS gBuffer.WorldPos + gBuffer.Normal * (dither * 0.1f + 0.1f)
|
||||
|
||||
#endif
|
||||
@@ -991,7 +994,7 @@ float4 PS_IndirectLighting(Quad_VS2PS input) : SV_Target0
|
||||
return float4(0, 0, 0, 0);
|
||||
|
||||
// Sample irradiance
|
||||
float dither = DDGI_GET_DITHER;
|
||||
float dither = DDGI_GET_DITHER * ResolveDitherScaleIndirect;
|
||||
float3 samplePos = DDGI_GET_SAMPLE_POS;
|
||||
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, samplePos, gBuffer.Normal, DDGI_DEFAULT_BIAS, dither);
|
||||
|
||||
@@ -1018,7 +1021,7 @@ float4 PS_SpecularLighting(Quad_VS2PS input) : SV_Target0
|
||||
return float4(0, 0, 0, 0);
|
||||
|
||||
// Sample specular reflection
|
||||
float dither = DDGI_GET_DITHER;
|
||||
float dither = DDGI_GET_DITHER * ResolveDitherScaleSpecular;
|
||||
float3 samplePos = DDGI_GET_SAMPLE_POS;
|
||||
float3 specular = SampleDDGISpecular(DDGI, ProbesData, ProbesDistance, ProbesRadiance, samplePos, gBuffer.Normal, gBuffer.Roughness, DDGI_DEFAULT_BIAS, dither);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user