diff --git a/Editor/GraphicsWindow.cpp b/Editor/GraphicsWindow.cpp index d3f703e47..29291df22 100644 --- a/Editor/GraphicsWindow.cpp +++ b/Editor/GraphicsWindow.cpp @@ -1029,6 +1029,26 @@ void GraphicsWindow::Create(EditorComponent* _editor) }); AddWidget(&ssrCheckBox); + ssrQualitySlider.Create(0, 2, 1, 2, "SSR.Quality: "); + ssrQualitySlider.SetText("Quality: "); + ssrQualitySlider.SetTooltip("Set render quality for screen space reflections."); + ssrQualitySlider.SetSize(XMFLOAT2(mod_wid, hei)); + ssrQualitySlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").Has("ssr_quality")) + { + editor->renderPath->setSSRQuality((wi::renderer::PostProcessQuality)editor->main->config.GetSection("graphics").GetInt("ssr_quality")); + } + ssrQualitySlider.OnSlide([=](wi::gui::EventArgs args) { + wi::renderer::PostProcessQuality quality = (wi::renderer::PostProcessQuality)args.iValue; + if (quality == editor->renderPath->getSSRQuality()) + return; + editor->renderPath->setSSRQuality(quality); + editor->renderPath->setSSREnabled(editor->renderPath->getSSREnabled()); + editor->main->config.GetSection("graphics").Set("ssr_quality", args.iValue); + editor->main->config.Commit(); + }); + AddWidget(&ssrQualitySlider); + reflectionsRoughnessCutoffSlider.Create(0, 1, 0.6f, 1000, "Cutoff: "); reflectionsRoughnessCutoffSlider.SetTooltip("Set maximum roughness which can be used to apply screen space or raytraced reflections."); reflectionsRoughnessCutoffSlider.SetSize(XMFLOAT2(mod_wid, hei)); @@ -1075,6 +1095,27 @@ void GraphicsWindow::Create(EditorComponent* _editor) AddWidget(&raytracedReflectionsRangeSlider); raytracedReflectionsRangeSlider.SetEnabled(wi::graphics::GetDevice()->CheckCapability(GraphicsDeviceCapability::RAYTRACING)); + raytracedReflectionsQualitySlider.Create(0, 2, 1, 2, "RTReflection.Quality: "); + raytracedReflectionsQualitySlider.SetText("Quality: "); + raytracedReflectionsQualitySlider.SetTooltip("Set render quality for Ray traced reflections."); + raytracedReflectionsQualitySlider.SetSize(XMFLOAT2(mod_wid, hei)); + raytracedReflectionsQualitySlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").Has("rtreflection_quality")) + { + editor->renderPath->setRaytracedReflectionsQuality((wi::renderer::PostProcessQuality)editor->main->config.GetSection("graphics").GetInt("rtreflection_quality")); + } + raytracedReflectionsQualitySlider.OnSlide([=](wi::gui::EventArgs args) { + wi::renderer::PostProcessQuality quality = (wi::renderer::PostProcessQuality)args.iValue; + if (quality == editor->renderPath->getRaytracedReflectionsQuality()) + return; + editor->renderPath->setRaytracedReflectionsQuality(quality); + editor->renderPath->setRaytracedReflectionsEnabled(editor->renderPath->getRaytracedReflectionEnabled()); + editor->main->config.GetSection("graphics").Set("rtreflection_quality", args.iValue); + editor->main->config.Commit(); + }); + AddWidget(&raytracedReflectionsQualitySlider); + raytracedReflectionsQualitySlider.SetEnabled(wi::graphics::GetDevice()->CheckCapability(GraphicsDeviceCapability::RAYTRACING)); + raytracedDiffuseCheckBox.Create("RT Diffuse: "); raytracedDiffuseCheckBox.SetTooltip("Enable Ray Traced Diffuse. Only if GPU supports raytracing.\nThis effect computes single bounce diffuse with ray tracing per pixel.\nIf DDGI is enabled, it will make it multi bounce."); raytracedDiffuseCheckBox.SetScriptTip("RenderPath3D::SetRaytracedDiffuseEnabled(bool value)"); @@ -1106,6 +1147,27 @@ void GraphicsWindow::Create(EditorComponent* _editor) AddWidget(&raytracedDiffuseRangeSlider); raytracedDiffuseRangeSlider.SetEnabled(wi::graphics::GetDevice()->CheckCapability(GraphicsDeviceCapability::RAYTRACING)); + raytracedDiffuseQualitySlider.Create(0, 2, 1, 2, "RTDiffuse.Quality: "); + raytracedDiffuseQualitySlider.SetText("Quality: "); + raytracedDiffuseQualitySlider.SetTooltip("Set render quality for Ray traced diffuse."); + raytracedDiffuseQualitySlider.SetSize(XMFLOAT2(mod_wid, hei)); + raytracedDiffuseQualitySlider.SetPos(XMFLOAT2(x + 100, y += step)); + if (editor->main->config.GetSection("graphics").Has("rtdiffuse_quality")) + { + editor->renderPath->setRaytracedDiffuseQuality((wi::renderer::PostProcessQuality)editor->main->config.GetSection("graphics").GetInt("rtdiffuse_quality")); + } + raytracedDiffuseQualitySlider.OnSlide([=](wi::gui::EventArgs args) { + wi::renderer::PostProcessQuality quality = (wi::renderer::PostProcessQuality)args.iValue; + if (quality == editor->renderPath->getRaytracedDiffuseQuality()) + return; + editor->renderPath->setRaytracedDiffuseQuality(quality); + editor->renderPath->setRaytracedDiffuseEnabled(editor->renderPath->getRaytracedDiffuseEnabled()); + editor->main->config.GetSection("graphics").Set("rtdiffuse_quality", args.iValue); + editor->main->config.Commit(); + }); + AddWidget(&raytracedDiffuseQualitySlider); + raytracedDiffuseQualitySlider.SetEnabled(wi::graphics::GetDevice()->CheckCapability(GraphicsDeviceCapability::RAYTRACING)); + ssgiCheckBox.Create("SSGI: "); ssgiCheckBox.SetTooltip("Enable Screen Space Global Illumination, this can add a light bounce effect coming from objects on the screen."); ssgiCheckBox.SetScriptTip("RenderPath3D::SetSSGIEnabled(bool value)"); @@ -1726,12 +1788,15 @@ void GraphicsWindow::UpdateData() aoSampleCountSlider.SetValue((float)editor->renderPath->getAOSampleCount()); reflectionsCheckBox.SetCheck(editor->renderPath->getReflectionsEnabled()); ssrCheckBox.SetCheck(editor->renderPath->getSSREnabled()); + ssrQualitySlider.SetValue((int)editor->renderPath->getSSRQuality()); reflectionsRoughnessCutoffSlider.SetValue(editor->renderPath->getReflectionRoughnessCutoff()); raytracedReflectionsCheckBox.SetCheck(editor->renderPath->getRaytracedReflectionEnabled()); raytracedReflectionsRangeSlider.SetValue(editor->renderPath->getRaytracedReflectionsRange()); + raytracedReflectionsQualitySlider.SetValue((int)editor->renderPath->getRaytracedReflectionsQuality()); raytracedDiffuseCheckBox.SetCheck(editor->renderPath->getRaytracedDiffuseEnabled()); ssgiCheckBox.SetCheck(editor->renderPath->getSSGIEnabled()); raytracedDiffuseRangeSlider.SetValue(editor->renderPath->getRaytracedDiffuseRange()); + raytracedDiffuseQualitySlider.SetValue((int)editor->renderPath->getRaytracedDiffuseQuality()); screenSpaceShadowsCheckBox.SetCheck(wi::renderer::GetScreenSpaceShadowsEnabled()); screenSpaceShadowsRangeSlider.SetValue((float)editor->renderPath->getScreenSpaceShadowRange()); ssgiDepthRejectionSlider.SetValue((float)editor->renderPath->getSSGIDepthRejection()); @@ -1974,12 +2039,15 @@ void GraphicsWindow::ResizeLayout() layout.add_right(reflectionsCheckBox); layout.add_right(reflectionsRoughnessCutoffSlider); ssrCheckBox.SetPos(XMFLOAT2(reflectionsRoughnessCutoffSlider.GetPos().x - ssrCheckBox.GetSize().x - 80, reflectionsRoughnessCutoffSlider.GetPos().y)); + layout.add_right(ssrQualitySlider); layout.add_right(raytracedReflectionsRangeSlider); raytracedReflectionsCheckBox.SetPos(XMFLOAT2(raytracedReflectionsRangeSlider.GetPos().x - raytracedReflectionsCheckBox.GetSize().x - 80, raytracedReflectionsRangeSlider.GetPos().y)); + layout.add_right(raytracedReflectionsQualitySlider); layout.add_right(ssgiDepthRejectionSlider); ssgiCheckBox.SetPos(XMFLOAT2(ssgiDepthRejectionSlider.GetPos().x - ssgiCheckBox.GetSize().x - 80, ssgiDepthRejectionSlider.GetPos().y)); layout.add_right(raytracedDiffuseRangeSlider); raytracedDiffuseCheckBox.SetPos(XMFLOAT2(raytracedDiffuseRangeSlider.GetPos().x - raytracedDiffuseCheckBox.GetSize().x - 80, raytracedDiffuseRangeSlider.GetPos().y)); + layout.add_right(raytracedDiffuseQualitySlider); layout.add_right(screenSpaceShadowsStepCountSlider); screenSpaceShadowsCheckBox.SetPos(XMFLOAT2(screenSpaceShadowsStepCountSlider.GetPos().x - screenSpaceShadowsCheckBox.GetSize().x - 80, screenSpaceShadowsStepCountSlider.GetPos().y)); layout.add_right(screenSpaceShadowsRangeSlider); diff --git a/Editor/GraphicsWindow.h b/Editor/GraphicsWindow.h index e68f2fbd7..8f871f8e3 100644 --- a/Editor/GraphicsWindow.h +++ b/Editor/GraphicsWindow.h @@ -68,11 +68,14 @@ public: wi::gui::Slider aoSampleCountSlider; wi::gui::CheckBox reflectionsCheckBox; wi::gui::CheckBox ssrCheckBox; + wi::gui::Slider ssrQualitySlider; wi::gui::CheckBox raytracedReflectionsCheckBox; wi::gui::Slider reflectionsRoughnessCutoffSlider; wi::gui::Slider raytracedReflectionsRangeSlider; + wi::gui::Slider raytracedReflectionsQualitySlider; wi::gui::CheckBox raytracedDiffuseCheckBox; wi::gui::Slider raytracedDiffuseRangeSlider; + wi::gui::Slider raytracedDiffuseQualitySlider; wi::gui::CheckBox ssgiCheckBox; wi::gui::Slider ssgiDepthRejectionSlider; wi::gui::CheckBox screenSpaceShadowsCheckBox; diff --git a/WickedEngine/shaders/ShaderInterop_Postprocess.h b/WickedEngine/shaders/ShaderInterop_Postprocess.h index 7170a5b88..6132a6bfb 100644 --- a/WickedEngine/shaders/ShaderInterop_Postprocess.h +++ b/WickedEngine/shaders/ShaderInterop_Postprocess.h @@ -43,6 +43,9 @@ struct Bloom static const uint SSR_TILESIZE = 32; #define ssr_roughness_cutoff postprocess.params0.z #define ssr_frame postprocess.params0.w +#define ssr_ratiofactorx postprocess.params1.x +#define ssr_ratiofactory postprocess.params1.y +#define ssr_downscalefactor postprocess.params1.z #define ssao_range postprocess.params0.x #define ssao_samplecount postprocess.params0.y @@ -55,11 +58,13 @@ static const uint SSR_TILESIZE = 32; #define rtdiffuse_range ssao_range #define rtdiffuse_frame ssr_frame +#define rtdiffuse_downscalefactor ssr_downscalefactor #define ssgi_frame ssr_frame #define rtreflection_range ssao_range #define rtreflection_roughness_cutoff ssr_roughness_cutoff #define rtreflection_frame ssr_frame +#define rtreflection_downscalefactor ssr_downscalefactor static const uint POSTPROCESS_HBAO_THREADCOUNT = 320; #define hbao_direction postprocess.params0.xy diff --git a/WickedEngine/shaders/rtdiffuseCS.hlsl b/WickedEngine/shaders/rtdiffuseCS.hlsl index e3b3feac0..3396c85cd 100644 --- a/WickedEngine/shaders/rtdiffuseCS.hlsl +++ b/WickedEngine/shaders/rtdiffuseCS.hlsl @@ -25,11 +25,9 @@ void main(uint2 DTid : SV_DispatchThreadID) { const float2 uv = ((float2)DTid.xy + 0.5) * postprocess.resolution_rcp; - const uint downsampleFactor = 2; - // This is necessary for accurate upscaling. This is so we don't reuse the same half-res pixels - uint2 screenJitter = floor(blue_noise(uint2(0, 0)).xy * downsampleFactor); - uint2 jitterPixel = screenJitter + DTid.xy * downsampleFactor; + uint2 screenJitter = floor(blue_noise(uint2(0, 0)).xy * rtdiffuse_downscalefactor); + uint2 jitterPixel = screenJitter + DTid.xy * rtdiffuse_downscalefactor; float2 jitterUV = (screenJitter + DTid.xy + 0.5f) * postprocess.resolution_rcp; const float depth = texture_depth.SampleLevel(sampler_linear_clamp, jitterUV, 0); diff --git a/WickedEngine/shaders/rtdiffuse_spatialCS.hlsl b/WickedEngine/shaders/rtdiffuse_spatialCS.hlsl index ee9909d54..d4075cd66 100644 --- a/WickedEngine/shaders/rtdiffuse_spatialCS.hlsl +++ b/WickedEngine/shaders/rtdiffuse_spatialCS.hlsl @@ -3,6 +3,8 @@ #include "stochasticSSRHF.hlsli" #include "ShaderInterop_Postprocess.h" +PUSHCONSTANT(postprocess, PostProcess); + Texture2D texture_rayIndirectDiffuse : register(t0); RWTexture2D texture_resolve : register(u0); @@ -59,13 +61,13 @@ void main(uint3 DTid : SV_DispatchThreadID) { const uint2 tracingCoord = DTid.xy; - const float depth = texture_depth[DTid.xy * 2]; + const float depth = texture_depth[DTid.xy * rtdiffuse_downscalefactor]; const float farplane = GetCamera().z_far; - const float lineardepth = texture_lineardepth[DTid.xy * 2] * farplane; + const float lineardepth = texture_lineardepth[DTid.xy * rtdiffuse_downscalefactor] * farplane; // Everthing in world space: - const float3 N = decode_oct(texture_normal[DTid.xy * 2]); + const float3 N = decode_oct(texture_normal[DTid.xy * rtdiffuse_downscalefactor]); float4 result = 0.0f; float weightSum = 0.0f; @@ -83,7 +85,7 @@ void main(uint3 DTid : SV_DispatchThreadID) float2 offset = (hammersley2d_random(i, sampleCount, random) - 0.5) * resolveSpatialSize; int2 neighborTracingCoord = tracingCoord + offset; - int2 neighborCoord = DTid.xy * 2 + offset; + int2 neighborCoord = DTid.xy * rtdiffuse_downscalefactor + offset; float neighbor_lineardepth = texture_lineardepth[neighborCoord] * farplane; if (neighbor_lineardepth < farplane) diff --git a/WickedEngine/shaders/rtdiffuse_temporalCS.hlsl b/WickedEngine/shaders/rtdiffuse_temporalCS.hlsl index 0dba3b621..7b7219158 100644 --- a/WickedEngine/shaders/rtdiffuse_temporalCS.hlsl +++ b/WickedEngine/shaders/rtdiffuse_temporalCS.hlsl @@ -141,7 +141,7 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV return; } - const float depth = texture_depth[DTid.xy * 2]; + const float depth = texture_depth[DTid.xy * rtdiffuse_downscalefactor]; // Welford's online algorithm: // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance @@ -166,7 +166,7 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV float4 variance = (m2 / 9.0) - (mean * mean); float4 stddev = sqrt(max(variance, 0.0f)); - float2 velocity = texture_velocity[DTid.xy * 2]; + float2 velocity = texture_velocity[DTid.xy * rtdiffuse_downscalefactor]; float2 uv = (DTid.xy + 0.5f) * postprocess.resolution_rcp; diff --git a/WickedEngine/shaders/rtreflectionCS.hlsl b/WickedEngine/shaders/rtreflectionCS.hlsl index e9c705c45..afdb02c84 100644 --- a/WickedEngine/shaders/rtreflectionCS.hlsl +++ b/WickedEngine/shaders/rtreflectionCS.hlsl @@ -27,7 +27,7 @@ void main(uint2 DTid : SV_DispatchThreadID) { const float2 uv = ((float2)DTid.xy + 0.5) * postprocess.resolution_rcp; - const uint downsampleFactor = 2; + const float downsampleFactor = rtreflection_downscalefactor; // This is necessary for accurate upscaling. This is so we don't reuse the same half-res pixels uint2 screenJitter = floor(blue_noise(uint2(0, 0)).xy * downsampleFactor); diff --git a/WickedEngine/shaders/ssr_depthHierarchyCS.hlsl b/WickedEngine/shaders/ssr_depthHierarchyCS.hlsl index 9111560a8..a99910c62 100644 --- a/WickedEngine/shaders/ssr_depthHierarchyCS.hlsl +++ b/WickedEngine/shaders/ssr_depthHierarchyCS.hlsl @@ -17,7 +17,7 @@ void main(uint3 DTid : SV_DispatchThreadID) uint2 dim; texture_depth.GetDimensions(dim.x, dim.y); - float2 uv = (DTid.xy + 0.5) / dim * 2; // Account for half-res + float2 uv = (DTid.xy + 0.5) / dim * ssr_downscalefactor; float4 depths = texture_depth.GatherRed(sampler_point_clamp, uv); diff --git a/WickedEngine/shaders/ssr_raytraceCS.hlsl b/WickedEngine/shaders/ssr_raytraceCS.hlsl index bcb43a685..d2f6b4bf5 100644 --- a/WickedEngine/shaders/ssr_raytraceCS.hlsl +++ b/WickedEngine/shaders/ssr_raytraceCS.hlsl @@ -227,10 +227,7 @@ float ValidateHit(float3 hit, float hitDepth, float2 prevHitUV) [numthreads(POSTPROCESS_BLOCKSIZE * POSTPROCESS_BLOCKSIZE, 1, 1)] void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) { - // This pass is rendered at half-res - const uint downsampleFactor = 2; - - const uint2 pixel = GetReflectionIndirectDispatchCoord(Gid, GTid, tiles, downsampleFactor); + const uint2 pixel = GetReflectionIndirectDispatchCoord(Gid, GTid, tiles, ssr_downscalefactor); const float2 uv = (pixel + 0.5f) * postprocess.resolution_rcp; #ifdef SSR_EARLYEXIT @@ -242,8 +239,8 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) #else // This is necessary for accurate upscaling. This is so we don't reuse the same half-res pixels - uint2 screenJitter = floor(blue_noise(uint2(0, 0)).xy * downsampleFactor); - uint2 jitterPixel = screenJitter + pixel * downsampleFactor; + uint2 screenJitter = floor(blue_noise(uint2(0, 0)).xy * ssr_downscalefactor); + uint2 jitterPixel = screenJitter + pixel * ssr_downscalefactor; float2 jitterUV = (screenJitter + pixel + 0.5f) * postprocess.resolution_rcp; // Due to HiZ tracing, the tracing and the pass components must match depth. @@ -330,9 +327,9 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) rayEndScreen.xy = rayEndScreen.xy * float2(0.5, -0.5) + float2(0.5, 0.5); #ifdef SSR_CHEAP - - rayStartScreen.xy *= postprocess.params1.xy; // Ratio factor between hierarchy and pass - rayEndScreen.xy *= postprocess.params1.xy; + const float2 ratiofactor = float2(ssr_ratiofactorx, ssr_ratiofactory); + rayStartScreen.xy *= ratiofactor; // Ratio factor between hierarchy and pass + rayEndScreen.xy *= ratiofactor; float3 rayDirectionScreen = rayEndScreen - rayStartScreen; @@ -342,7 +339,7 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) bool validHit = false; float3 hit = RayMarch(rayStartScreen, rayDirectionScreen, roughness, jitter, validHit); - hit.xy *= postprocess.params1.zw; // Undo ratio + hit.xy /= ratiofactor; // Undo ratio #else diff --git a/WickedEngine/shaders/ssr_resolveCS.hlsl b/WickedEngine/shaders/ssr_resolveCS.hlsl index b90b18231..0cee1397a 100644 --- a/WickedEngine/shaders/ssr_resolveCS.hlsl +++ b/WickedEngine/shaders/ssr_resolveCS.hlsl @@ -88,8 +88,8 @@ void main(uint3 DTid : SV_DispatchThreadID) { const float2 uv = (DTid.xy + 0.5) * postprocess.resolution_rcp; - const float depth = texture_depth[DTid.xy * 2]; - const float roughness = texture_roughness[DTid.xy * 2]; + const float depth = texture_depth[DTid.xy * ssr_downscalefactor]; + const float roughness = texture_roughness[DTid.xy * ssr_downscalefactor]; if (!NeedReflection(roughness, depth, ssr_roughness_cutoff)) { @@ -101,7 +101,7 @@ void main(uint3 DTid : SV_DispatchThreadID) // Everthing in world space: const float3 P = reconstruct_position(uv, depth); - const float3 N = decode_oct(texture_normal[DTid.xy * 2]); + const float3 N = decode_oct(texture_normal[DTid.xy * ssr_downscalefactor]); const float3 V = normalize(GetCamera().frustum_corners.screen_to_nearplane(uv) - P); // ortho support const float NdotV = saturate(dot(N, V)); @@ -125,7 +125,7 @@ void main(uint3 DTid : SV_DispatchThreadID) int2 neighborCoord = DTid.xy + offset; - float neighborDepth = texture_depth[neighborCoord * 2]; + float neighborDepth = texture_depth[neighborCoord * ssr_downscalefactor]; if (neighborDepth > 0.0) { float weight = GetWeight(neighborCoord, V, N, roughness, NdotV); @@ -153,7 +153,7 @@ void main(uint3 DTid : SV_DispatchThreadID) float resolveVariance = S / weightSum; // Convert to post-projection depth so we can construct dual source reprojection buffers later - const float lineardepth = texture_lineardepth[DTid.xy * 2] * GetCamera().z_far; + const float lineardepth = texture_lineardepth[DTid.xy * ssr_downscalefactor] * GetCamera().z_far; float reprojectionDepth = compute_inverse_lineardepth(lineardepth + closestRayLength); texture_resolve[DTid.xy] = max(result, 0.00001f); diff --git a/WickedEngine/shaders/ssr_temporalCS.hlsl b/WickedEngine/shaders/ssr_temporalCS.hlsl index e968e99a5..63f4d9b15 100644 --- a/WickedEngine/shaders/ssr_temporalCS.hlsl +++ b/WickedEngine/shaders/ssr_temporalCS.hlsl @@ -141,8 +141,8 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV return; } - const float depth = texture_depth[DTid.xy * 2]; - const float roughness = texture_roughness[DTid.xy * 2]; + const float depth = texture_depth[DTid.xy * ssr_downscalefactor]; + const float roughness = texture_roughness[DTid.xy * ssr_downscalefactor]; if (!NeedReflection(roughness, depth, ssr_roughness_cutoff)) { @@ -177,7 +177,7 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint3 DTid : SV // Secondary reprojection based on ray lengths: // https://www.ea.com/seed/news/seed-dd18-presentation-slides-raytracing (Slide 45) - float2 velocity = texture_velocity[DTid.xy * 2]; + float2 velocity = texture_velocity[DTid.xy * ssr_downscalefactor]; float reprojectionDepth = texture_reprojectionDepth[DTid.xy]; float2 uv = (DTid.xy + 0.5f) * postprocess.resolution_rcp; diff --git a/WickedEngine/shaders/ssr_tileMaxRoughness_verticalCS.hlsl b/WickedEngine/shaders/ssr_tileMaxRoughness_verticalCS.hlsl index 27669ad7a..83037a8dd 100644 --- a/WickedEngine/shaders/ssr_tileMaxRoughness_verticalCS.hlsl +++ b/WickedEngine/shaders/ssr_tileMaxRoughness_verticalCS.hlsl @@ -14,7 +14,6 @@ RWStructuredBuffer tiles_tracing_expensive : register(u3); RWTexture2D tile_minmax_roughness : register(u4); static const float SSRRoughnessCheap = 0.35; -static const uint tile_tracing_replicate = sqr(SSR_TILESIZE / 2 / POSTPROCESS_BLOCKSIZE); [numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) @@ -39,6 +38,7 @@ void main(uint3 DTid : SV_DispatchThreadID) } const uint tile = (DTid.x & 0xFFFF) | ((DTid.y & 0xFFFF) << 16); + const uint tile_tracing_replicate = sqr(SSR_TILESIZE / ssr_downscalefactor / POSTPROCESS_BLOCKSIZE); uint prevCount; if (minRoughness < SSRRoughnessCheap) diff --git a/WickedEngine/wiRenderPath3D.cpp b/WickedEngine/wiRenderPath3D.cpp index 2d1a4efe1..b701c4810 100644 --- a/WickedEngine/wiRenderPath3D.cpp +++ b/WickedEngine/wiRenderPath3D.cpp @@ -2858,7 +2858,7 @@ namespace wi device->CreateTexture(&desc, nullptr, &rtSSR); device->SetName(&rtSSR, "rtSSR"); - wi::renderer::CreateSSRResources(ssrResources, internalResolution); + wi::renderer::CreateSSRResources(ssrResources, internalResolution, ssrQuality); } else { @@ -2911,7 +2911,7 @@ namespace wi device->CreateTexture(&desc, nullptr, &rtSSR); device->SetName(&rtSSR, "rtSSR"); - wi::renderer::CreateRTReflectionResources(rtreflectionResources, internalResolution); + wi::renderer::CreateRTReflectionResources(rtreflectionResources, internalResolution, raytracedReflectionsQuality); } else { @@ -2937,7 +2937,7 @@ namespace wi device->CreateTexture(&desc, nullptr, &rtRaytracedDiffuse); device->SetName(&rtRaytracedDiffuse, "rtRaytracedDiffuse"); - wi::renderer::CreateRTDiffuseResources(rtdiffuseResources, internalResolution); + wi::renderer::CreateRTDiffuseResources(rtdiffuseResources, internalResolution, raytracedDiffuseQuality); } else { diff --git a/WickedEngine/wiRenderPath3D.h b/WickedEngine/wiRenderPath3D.h index 985e391c3..b2c8050dd 100644 --- a/WickedEngine/wiRenderPath3D.h +++ b/WickedEngine/wiRenderPath3D.h @@ -59,6 +59,9 @@ namespace wi float ssgiDepthRejection = 8; wi::renderer::Tonemap tonemap = wi::renderer::Tonemap::ACES; float hdr_calibration = 1; + wi::renderer::PostProcessQuality raytracedDiffuseQuality = wi::renderer::PostProcessQuality::Medium; + wi::renderer::PostProcessQuality raytracedReflectionsQuality = wi::renderer::PostProcessQuality::Medium; + wi::renderer::PostProcessQuality ssrQuality = wi::renderer::PostProcessQuality::Medium; AO ao = AO_DISABLED; bool fxaaEnabled = false; @@ -252,6 +255,9 @@ namespace wi constexpr float getReflectionRoughnessCutoff() const { return reflectionRoughnessCutoff; } constexpr float getSSGIDepthRejection() const { return ssgiDepthRejection; } constexpr wi::renderer::Tonemap getTonemap() const { return tonemap; } + constexpr wi::renderer::PostProcessQuality getRaytracedDiffuseQuality() const { return raytracedDiffuseQuality; } + constexpr wi::renderer::PostProcessQuality getRaytracedReflectionsQuality() const { return raytracedReflectionsQuality; } + constexpr wi::renderer::PostProcessQuality getSSRQuality() const { return ssrQuality; } constexpr bool getAOEnabled() const { return ao != AO_DISABLED; } constexpr AO getAO() const { return ao; } @@ -312,6 +318,9 @@ namespace wi constexpr void setSSGIDepthRejection(float value) { ssgiDepthRejection = value; } constexpr void setTonemap(wi::renderer::Tonemap value) { tonemap = value; } constexpr void setVisibilityComputeShadingEnabled(bool value) { visibility_shading_in_compute = value; } + constexpr void setRaytracedDiffuseQuality(wi::renderer::PostProcessQuality value) { raytracedDiffuseQuality = value; } + constexpr void setRaytracedReflectionsQuality(wi::renderer::PostProcessQuality value) { raytracedReflectionsQuality = value; } + constexpr void setSSRQuality(wi::renderer::PostProcessQuality value) { ssrQuality = value; } void setAO(AO value); void setSSREnabled(bool value); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 6da19b738..a87e5327b 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -13712,14 +13712,16 @@ void Postprocess_RTAO( wi::profiler::EndRange(prof_range); device->EventEnd(cmd); } -void CreateRTDiffuseResources(RTDiffuseResources& res, XMUINT2 resolution) +void CreateRTDiffuseResources(RTDiffuseResources& res, XMUINT2 resolution, PostProcessQuality quality) { res.frame = 0; + res.quality = quality; + const uint32_t downscale = quality_downscalefactor(quality); TextureDesc desc; desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = resolution.x / 2; - desc.height = resolution.y / 2; + desc.width = resolution.x / downscale; + desc.height = resolution.y / downscale; desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; @@ -13800,16 +13802,14 @@ void Postprocess_RTDiffuse( BindCommonResources(cmd); - const TextureDesc& desc = output.desc; - - // Render half-res: PostProcess postprocess; - postprocess.resolution.x = desc.width / 2; - postprocess.resolution.y = desc.height / 2; + postprocess.resolution.x = res.texture_rayIndirectDiffuse.desc.width; + postprocess.resolution.y = res.texture_rayIndirectDiffuse.desc.height; postprocess.resolution_rcp.x = 1.0f / postprocess.resolution.x; postprocess.resolution_rcp.y = 1.0f / postprocess.resolution.y; rtdiffuse_range = range; rtdiffuse_frame = (float)res.frame; + rtdiffuse_downscalefactor = quality_downscalefactor(res.quality); uint8_t instanceInclusionMask = 0xFF; std::memcpy(&postprocess.params1.x, &instanceInclusionMask, sizeof(instanceInclusionMask)); @@ -13847,6 +13847,8 @@ void Postprocess_RTDiffuse( device->EventBegin("RTDiffuse - spatial resolve", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTDIFFUSE_SPATIAL], cmd); + device->PushConstants(&postprocess, sizeof(postprocess), cmd); + const GPUResource* resarray[] = { &res.texture_rayIndirectDiffuse, }; @@ -13915,6 +13917,8 @@ void Postprocess_RTDiffuse( device->EventEnd(cmd); } + const TextureDesc& desc = output.desc; + // Full res: postprocess.resolution.x = desc.width; postprocess.resolution.y = desc.height; @@ -14399,14 +14403,16 @@ void Postprocess_SSGI( wi::profiler::EndRange(profilerRange); device->EventEnd(cmd); } -void CreateRTReflectionResources(RTReflectionResources& res, XMUINT2 resolution) +void CreateRTReflectionResources(RTReflectionResources& res, XMUINT2 resolution, PostProcessQuality quality) { res.frame = 0; + res.quality = quality; + const uint32_t downscale = quality_downscalefactor(quality); TextureDesc desc; desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = resolution.x / 2; - desc.height = resolution.y / 2; + desc.width = resolution.x / downscale; + desc.height = resolution.y / downscale; desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; @@ -14417,8 +14423,6 @@ void CreateRTReflectionResources(RTReflectionResources& res, XMUINT2 resolution) device->CreateTexture(&desc, nullptr, &res.texture_rayLengths); device->SetName(&res.texture_rayLengths, "ssr_rayLengths"); - desc.width = resolution.x / 2; - desc.height = resolution.y / 2; desc.format = Format::R16G16B16A16_FLOAT; device->CreateTexture(&desc, nullptr, &res.texture_resolve); device->CreateTexture(&desc, nullptr, &res.texture_temporal[0]); @@ -14495,17 +14499,15 @@ void Postprocess_RTReflection( device->ClearUAV(&output, 0, cmd); - const TextureDesc& desc = output.desc; - - // Render half-res: PostProcess postprocess; - postprocess.resolution.x = desc.width / 2; - postprocess.resolution.y = desc.height / 2; + postprocess.resolution.x = res.texture_rayIndirectSpecular.desc.width; + postprocess.resolution.y = res.texture_rayIndirectSpecular.desc.height; postprocess.resolution_rcp.x = 1.0f / postprocess.resolution.x; postprocess.resolution_rcp.y = 1.0f / postprocess.resolution.y; rtreflection_range = range; rtreflection_roughness_cutoff = roughnessCutoff; rtreflection_frame = (float)res.frame; + rtreflection_downscalefactor = quality_downscalefactor(res.quality); uint8_t instanceInclusionMask = raytracing_inclusion_mask_reflection; std::memcpy(&postprocess.params1.x, &instanceInclusionMask, sizeof(instanceInclusionMask)); @@ -14686,6 +14688,8 @@ void Postprocess_RTReflection( device->EventEnd(cmd); } + const TextureDesc& desc = output.desc; + // Upscale to full-res: postprocess.resolution.x = desc.width; postprocess.resolution.y = desc.height; @@ -14731,9 +14735,11 @@ void Postprocess_RTReflection( wi::profiler::EndRange(profilerRange); device->EventEnd(cmd); } -void CreateSSRResources(SSRResources& res, XMUINT2 resolution) +void CreateSSRResources(SSRResources& res, XMUINT2 resolution, PostProcessQuality quality) { res.frame = 0; + res.quality = quality; + const uint32_t downscale = quality_downscalefactor(quality); TextureDesc tile_desc; tile_desc.type = TextureDesc::Type::TEXTURE_2D; @@ -14765,8 +14771,8 @@ void CreateSSRResources(SSRResources& res, XMUINT2 resolution) TextureDesc desc; desc.type = TextureDesc::Type::TEXTURE_2D; - desc.width = resolution.x / 2; - desc.height = resolution.y / 2; + desc.width = resolution.x / downscale; + desc.height = resolution.y / downscale; desc.format = Format::R16G16B16A16_FLOAT; desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; desc.layout = ResourceState::SHADER_RESOURCE_COMPUTE; @@ -14775,9 +14781,6 @@ void CreateSSRResources(SSRResources& res, XMUINT2 resolution) desc.format = Format::R16_FLOAT; device->CreateTexture(&desc, nullptr, &res.texture_rayLengths); device->SetName(&res.texture_rayLengths, "ssr_rayLengths"); - - desc.width = resolution.x / 2; - desc.height = resolution.y / 2; desc.format = Format::R16G16B16A16_FLOAT; device->CreateTexture(&desc, nullptr, &res.texture_resolve); device->CreateTexture(&desc, nullptr, &res.texture_temporal[0]); @@ -14788,8 +14791,8 @@ void CreateSSRResources(SSRResources& res, XMUINT2 resolution) device->CreateTexture(&desc, nullptr, &res.texture_temporal_variance[0]); device->CreateTexture(&desc, nullptr, &res.texture_temporal_variance[1]); - desc.width = (uint32_t)std::pow(2.0f, 1.0f + std::floor(std::log2((float)resolution.x / 2))); - desc.height = (uint32_t)std::pow(2.0f, 1.0f + std::floor(std::log2((float)resolution.y / 2))); + desc.width = (uint32_t)std::pow(2.0f, 1.0f + std::floor(std::log2((float)resolution.x / downscale))); + desc.height = (uint32_t)std::pow(2.0f, 1.0f + std::floor(std::log2((float)resolution.y / downscale))); desc.format = Format::R32G32_FLOAT; desc.mip_levels = 1 + (uint32_t)std::floor(std::log2f(std::max((float)desc.width, (float)desc.height))); device->CreateTexture(&desc, nullptr, &res.texture_depth_hierarchy); @@ -14822,6 +14825,9 @@ void Postprocess_SSR( { GPUBarrier barriers[] = { + GPUBarrier::Image(&res.texture_rayIndirectSpecular, res.texture_rayIndirectSpecular.desc.layout, ResourceState::UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_rayDirectionPDF, res.texture_rayDirectionPDF.desc.layout, ResourceState::UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_rayLengths, res.texture_rayLengths.desc.layout, ResourceState::UNORDERED_ACCESS), GPUBarrier::Image(&res.texture_tile_minmax_roughness_horizontal, res.texture_tile_minmax_roughness_horizontal.desc.layout, ResourceState::UNORDERED_ACCESS), GPUBarrier::Image(&res.texture_tile_minmax_roughness, res.texture_tile_minmax_roughness.desc.layout, ResourceState::UNORDERED_ACCESS), GPUBarrier::Image(&res.texture_resolve, res.texture_resolve.desc.layout, ResourceState::UNORDERED_ACCESS), @@ -14843,6 +14849,9 @@ void Postprocess_SSR( }; device->Barrier(barriers, arraysize(barriers), cmd); } + device->ClearUAV(&res.texture_rayIndirectSpecular, 0, cmd); + device->ClearUAV(&res.texture_rayDirectionPDF, 0, cmd); + device->ClearUAV(&res.texture_rayLengths, 0, cmd); device->ClearUAV(&res.texture_tile_minmax_roughness_horizontal, 0, cmd); device->ClearUAV(&res.texture_tile_minmax_roughness, 0, cmd); device->ClearUAV(&res.texture_resolve, 0, cmd); @@ -14886,6 +14895,7 @@ void Postprocess_SSR( PostProcess postprocess; ssr_roughness_cutoff = roughnessCutoff; ssr_frame = (float)res.frame; + ssr_downscalefactor = quality_downscalefactor(res.quality); // Compute tile classification (horizontal): { @@ -15029,21 +15039,16 @@ void Postprocess_SSR( device->EventEnd(cmd); } - const TextureDesc& desc = output.GetDesc(); - // Render half-res: - postprocess.resolution.x = desc.width / 2; - postprocess.resolution.y = desc.height / 2; + postprocess.resolution.x = res.texture_rayIndirectSpecular.desc.width; + postprocess.resolution.y = res.texture_rayIndirectSpecular.desc.height; postprocess.resolution_rcp.x = 1.0f / postprocess.resolution.x; postprocess.resolution_rcp.y = 1.0f / postprocess.resolution.y; ssr_roughness_cutoff = roughnessCutoff; ssr_frame = (float)res.frame; - - // Factor to scale ratio between hierarchy and trace pass - postprocess.params1.x = (float)postprocess.resolution.x / (float)res.texture_depth_hierarchy.GetDesc().width; - postprocess.params1.y = (float)postprocess.resolution.y / (float)res.texture_depth_hierarchy.GetDesc().height; - postprocess.params1.z = 1.0f / postprocess.params1.x; - postprocess.params1.w = 1.0f / postprocess.params1.y; + ssr_ratiofactorx = (float)postprocess.resolution.x / (float)res.texture_depth_hierarchy.GetDesc().width; + ssr_ratiofactory = (float)postprocess.resolution.y / (float)res.texture_depth_hierarchy.GetDesc().height; + ssr_downscalefactor = quality_downscalefactor(res.quality); // Raytrace pass: { @@ -15071,9 +15076,6 @@ void Postprocess_SSR( GPUBarrier::Buffer(&res.buffer_tiles_tracing_earlyexit, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE), GPUBarrier::Buffer(&res.buffer_tiles_tracing_cheap, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE), GPUBarrier::Buffer(&res.buffer_tiles_tracing_expensive, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE), - GPUBarrier::Image(&res.texture_rayIndirectSpecular, res.texture_rayIndirectSpecular.desc.layout, ResourceState::UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_rayDirectionPDF, res.texture_rayDirectionPDF.desc.layout, ResourceState::UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_rayLengths, res.texture_rayLengths.desc.layout, ResourceState::UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -15180,6 +15182,8 @@ void Postprocess_SSR( device->EventEnd(cmd); } + const TextureDesc& desc = output.GetDesc(); + // Upscale to full-res: postprocess.resolution.x = desc.width; postprocess.resolution.y = desc.height; diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 41dd5a0e8..5630faa5e 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -458,6 +458,27 @@ namespace wi::renderer wi::graphics::CommandList cmd ); + enum class PostProcessQuality + { + Low, + Medium, + High + }; + inline constexpr uint32_t quality_downscalefactor(PostProcessQuality quality) + { + switch (quality) + { + case wi::renderer::PostProcessQuality::Low: + return 4; + case wi::renderer::PostProcessQuality::Medium: + return 2; + case wi::renderer::PostProcessQuality::High: + default: + break; + } + return 1; + } + // Surfel GI: diffuse GI with ray tracing from surfels struct SurfelGIResources { @@ -604,13 +625,14 @@ namespace wi::renderer struct RTDiffuseResources { mutable int frame = 0; + PostProcessQuality quality = PostProcessQuality::Medium; wi::graphics::Texture texture_rayIndirectDiffuse; wi::graphics::Texture texture_spatial; wi::graphics::Texture texture_spatial_variance; wi::graphics::Texture texture_temporal[2]; wi::graphics::Texture texture_temporal_variance[2]; }; - void CreateRTDiffuseResources(RTDiffuseResources& res, XMUINT2 resolution); + void CreateRTDiffuseResources(RTDiffuseResources& res, XMUINT2 resolution, PostProcessQuality quality = PostProcessQuality::Medium); void Postprocess_RTDiffuse( const RTDiffuseResources& res, const wi::scene::Scene& scene, @@ -640,6 +662,7 @@ namespace wi::renderer struct RTReflectionResources { mutable int frame = 0; + PostProcessQuality quality = PostProcessQuality::Medium; wi::graphics::Texture texture_rayIndirectSpecular; wi::graphics::Texture texture_rayDirectionPDF; wi::graphics::Texture texture_rayLengths; @@ -649,7 +672,7 @@ namespace wi::renderer wi::graphics::Texture texture_temporal[2]; wi::graphics::Texture texture_temporal_variance[2]; }; - void CreateRTReflectionResources(RTReflectionResources& res, XMUINT2 resolution); + void CreateRTReflectionResources(RTReflectionResources& res, XMUINT2 resolution, PostProcessQuality quality = PostProcessQuality::Medium); void Postprocess_RTReflection( const RTReflectionResources& res, const wi::scene::Scene& scene, @@ -661,6 +684,7 @@ namespace wi::renderer struct SSRResources { mutable int frame = 0; + PostProcessQuality quality = PostProcessQuality::Medium; wi::graphics::Texture texture_tile_minmax_roughness_horizontal; wi::graphics::Texture texture_tile_minmax_roughness; wi::graphics::Texture texture_depth_hierarchy; @@ -677,7 +701,7 @@ namespace wi::renderer wi::graphics::GPUBuffer buffer_tiles_tracing_cheap; wi::graphics::GPUBuffer buffer_tiles_tracing_expensive; }; - void CreateSSRResources(SSRResources& res, XMUINT2 resolution); + void CreateSSRResources(SSRResources& res, XMUINT2 resolution, PostProcessQuality quality = PostProcessQuality::Medium); void Postprocess_SSR( const SSRResources& res, const wi::graphics::Texture& input,