diff --git a/features/Screen Space GI/Shaders/ScreenSpaceGI/blur.cs.hlsl b/features/Screen Space GI/Shaders/ScreenSpaceGI/blur.cs.hlsl index 9589288b8..5c8b5a25c 100644 --- a/features/Screen Space GI/Shaders/ScreenSpaceGI/blur.cs.hlsl +++ b/features/Screen Space GI/Shaders/ScreenSpaceGI/blur.cs.hlsl @@ -48,9 +48,9 @@ float HistoryRadiusScaling(float accumFrames) uint eyeIndex = GetEyeIndexFromTexCoord(uv); const float2 screenPos = ConvertFromStereoUV(uv, eyeIndex); - float depth = READ_DEPTH(srcDepth, dtid); + float depth = srcDepth[dtid]; float3 pos = ScreenToViewPosition(screenPos, depth, eyeIndex); - float3 normal = DecodeNormal(FULLRES_LOAD(srcNormal, dtid, uv, samplerLinearClamp).xy); + float3 normal = DecodeNormal(srcNormal[dtid].xy); float4 sum = srcGI[dtid]; #ifdef TEMPORAL_DENOISER diff --git a/features/Screen Space GI/Shaders/ScreenSpaceGI/common.hlsli b/features/Screen Space GI/Shaders/ScreenSpaceGI/common.hlsli index b34bdf6e3..d60b78c41 100644 --- a/features/Screen Space GI/Shaders/ScreenSpaceGI/common.hlsli +++ b/features/Screen Space GI/Shaders/ScreenSpaceGI/common.hlsli @@ -70,18 +70,6 @@ SamplerState samplerLinearClamp : register(s1); /////////////////////////////////////////////////////////////////////////////// -// screenPos - normalised position in FrameDim, one eye only -// uv - normalised position in FrameDim, both eye -// texCoord - texture coordinate - -#ifdef HALF_RES -# define READ_DEPTH(tex, px) tex.Load(int3(px, 1)) -# define FULLRES_LOAD(tex, px, texCoord, samp) tex.SampleLevel(samp, texCoord, 0) -#else -# define READ_DEPTH(tex, px) tex[px] -# define FULLRES_LOAD(tex, px, texCoord, samp) tex[px] -#endif - /////////////////////////////////////////////////////////////////////////////// #define ISNAN(x) (!(x < 0.f || x > 0.f || x == 0.f)) diff --git a/features/Screen Space GI/Shaders/ScreenSpaceGI/fast_2uges.dds b/features/Screen Space GI/Shaders/ScreenSpaceGI/fast_2uges.dds new file mode 100644 index 000000000..a7a42c548 Binary files /dev/null and b/features/Screen Space GI/Shaders/ScreenSpaceGI/fast_2uges.dds differ diff --git a/features/Screen Space GI/Shaders/ScreenSpaceGI/gi.cs.hlsl b/features/Screen Space GI/Shaders/ScreenSpaceGI/gi.cs.hlsl index f24b8ac3e..a1f776add 100644 --- a/features/Screen Space GI/Shaders/ScreenSpaceGI/gi.cs.hlsl +++ b/features/Screen Space GI/Shaders/ScreenSpaceGI/gi.cs.hlsl @@ -28,20 +28,16 @@ #include "../Common/VR.hlsli" #include "common.hlsli" -#if USE_HALF_FLOAT_PRECISION == 0 -# define PI (3.1415926535897932384626433832795) -# define HALF_PI (1.5707963267948966192313216916398) -# define RCP_PI (0.31830988618) -#else -# define PI (3.1415926535897932384626433832795) -# define HALF_PI (1.5707963267948966192313216916398) -# define RCP_PI (0.31830988618) -#endif +#define FP_Z (16.5) + +#define PI (3.1415926535897932384626433832795) +#define HALF_PI (1.5707963267948966192313216916398) +#define RCP_PI (0.31830988618) Texture2D srcWorkingDepth : register(t0); Texture2D srcNormal : register(t1); Texture2D srcRadiance : register(t2); // maybe half-res -Texture2D srcHilbertLUT : register(t3); +Texture2D srcNoise : register(t3); Texture2D srcAccumFrames : register(t4); // maybe half-res Texture2D srcPrevGI : register(t5); // maybe half-res @@ -57,12 +53,10 @@ float GetDepthFade(float depth) // Engine-specific screen & temporal noise loader float2 SpatioTemporalNoise(uint2 pixCoord, uint temporalIndex) // without TAA, temporalIndex is always 0 { - float2 noise; - uint index = srcHilbertLUT.Load(uint3(pixCoord % 64, 0)).x; - index += 288 * (temporalIndex % 64); // why 288? tried out a few and that's the best so far (with XE_HILBERT_LEVEL 6U) - but there's probably better :) - // R2 sequence - see http://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/ - // https://www.shadertoy.com/view/mts3zN - return float2(frac(0.5 + index * float2(0.245122333753, 0.430159709002))); + // noise texture from https://github.com/electronicarts/fastnoise + // 128x128x64 + uint2 noiseCoord = (pixCoord % 128) + uint2(0, (temporalIndex % 64) * 128); + return srcNoise.Load(uint3(noiseCoord, 0)); } // HBIL pp.29 @@ -176,12 +170,9 @@ void CalculateGI( float sampleOffsetLength = length(sampleOffset); float mipLevel = clamp(log2(sampleOffsetLength) - DepthMIPSamplingOffset, 0, 5); -#ifdef HALF_RES - mipLevel = max(mipLevel, 1); -#endif float SZ = srcWorkingDepth.SampleLevel(samplerPointClamp, sampleUV * srcScale, mipLevel); - [branch] if (SZ > DepthFadeRange.y) continue; + [branch] if (SZ > DepthFadeRange.y || SZ < FP_Z) continue; float3 samplePos = ScreenToViewPosition(sampleScreenPos, SZ, eyeIndex); float3 sampleDelta = samplePos - float3(pixCenterPos); @@ -357,16 +348,23 @@ void CalculateGI( const float2 srcScale = SrcFrameDim * RcpTexDim; const float2 outScale = OutFrameDim * RcpTexDim; - float2 uv = (dtid + .5f) * RcpOutFrameDim; + uint2 pxCoord = dtid; +#if defined(HALF_RATE) + const uint halfWidth = uint(OutFrameDim.x) >> 1; + const bool useHistory = dtid.x >= halfWidth; + pxCoord.x = (pxCoord.x % halfWidth) * 2 + (dtid.y + FrameIndex + useHistory) % 2; +#endif + + float2 uv = (pxCoord + .5f) * RcpOutFrameDim; uint eyeIndex = GetEyeIndexFromTexCoord(uv); - float viewspaceZ = READ_DEPTH(srcWorkingDepth, dtid); + float viewspaceZ = srcWorkingDepth[pxCoord]; - float2 normalSample = FULLRES_LOAD(srcNormal, dtid, uv * srcScale, samplerLinearClamp).xy; + float2 normalSample = srcNormal[pxCoord].xy; float3 viewspaceNormal = DecodeNormal(normalSample); half2 encodedWorldNormal = EncodeNormal(ViewToWorldVector(viewspaceNormal, CameraViewInverse[eyeIndex])); - outPrevGeo[dtid] = half3(viewspaceZ, encodedWorldNormal); + outPrevGeo[pxCoord] = half3(viewspaceZ, encodedWorldNormal); // Move center pixel slightly towards camera to avoid imprecision artifacts due to depth buffer imprecision; offset depends on depth texture format used #if USE_HALF_FLOAT_PRECISION == 1 @@ -377,25 +375,34 @@ void CalculateGI( float4 currGIAO = float4(0, 0, 0, 1); float3 bentNormal = viewspaceNormal; - [branch] if (viewspaceZ < DepthFadeRange.y) + + bool needGI = viewspaceZ > FP_Z && viewspaceZ < DepthFadeRange.y; +#if defined(HALF_RATE) + needGI = needGI && !useHistory; +#endif + [branch] if (needGI) CalculateGI( - dtid, uv, viewspaceZ, viewspaceNormal, + pxCoord, uv, viewspaceZ, viewspaceNormal, currGIAO, bentNormal); #ifdef BENT_NORMAL - outBentNormal[dtid] = EncodeNormal(bentNormal); + outBentNormal[pxCoord] = EncodeNormal(bentNormal); #endif #ifdef TEMPORAL_DENOISER if (viewspaceZ < DepthFadeRange.y) { - float4 prevGIAO = srcPrevGI[dtid]; - uint accumFrames = srcAccumFrames[dtid] * 255; + float lerpFactor = 0; +# if defined(HALF_RATE) + if (!useHistory) +# endif + lerpFactor = rcp(srcAccumFrames[pxCoord] * 255); - currGIAO = lerp(prevGIAO, currGIAO, rcp(accumFrames)); + float4 prevGIAO = srcPrevGI[pxCoord]; + currGIAO = lerp(prevGIAO, currGIAO, lerpFactor); } #endif currGIAO = any(ISNAN(currGIAO)) ? float4(0, 0, 0, 1) : currGIAO; - outGI[dtid] = currGIAO; + outGI[pxCoord] = currGIAO; } \ No newline at end of file diff --git a/features/Screen Space GI/Shaders/ScreenSpaceGI/hilbert.cs.hlsl b/features/Screen Space GI/Shaders/ScreenSpaceGI/hilbert.cs.hlsl deleted file mode 100644 index 03ae75e8d..000000000 --- a/features/Screen Space GI/Shaders/ScreenSpaceGI/hilbert.cs.hlsl +++ /dev/null @@ -1,46 +0,0 @@ -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016-2021, Intel Corporation -// -// SPDX-License-Identifier: MIT -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// XeGTAO is based on GTAO/GTSO "Jimenez et al. / Practical Real-Time Strategies for Accurate Indirect Occlusion", -// https://www.activision.com/cdn/research/Practical_Real_Time_Strategies_for_Accurate_Indirect_Occlusion_NEW%20VERSION_COLOR.pdf -// -// Implementation: Filip Strugar (filip.strugar@intel.com), Steve Mccalla (\_/) -// Version: (see XeGTAO.h) (='.'=) -// Details: https://github.com/GameTechDev/XeGTAO (")_(") -// -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -RWTexture2D outHilbertLUT : register(u0); - -// From https://www.shadertoy.com/view/3tB3z3 - except we're using R2 here -#define XE_HILBERT_LEVEL 6U -#define XE_HILBERT_WIDTH ((1U << XE_HILBERT_LEVEL)) -#define XE_HILBERT_AREA (XE_HILBERT_WIDTH * XE_HILBERT_WIDTH) -inline uint HilbertIndex(uint posX, uint posY) -{ - uint index = 0U; - for (uint curLevel = XE_HILBERT_WIDTH / 2U; curLevel > 0U; curLevel /= 2U) { - uint regionX = (posX & curLevel) > 0U; - uint regionY = (posY & curLevel) > 0U; - index += curLevel * curLevel * ((3U * regionX) ^ regionY); - if (regionY == 0U) { - if (regionX == 1U) { - posX = uint((XE_HILBERT_WIDTH - 1U)) - posX; - posY = uint((XE_HILBERT_WIDTH - 1U)) - posY; - } - - uint temp = posX; - posX = posY; - posY = temp; - } - } - return index; -} - -[numthreads(32, 32, 1)] void main(uint2 tid - : SV_DispatchThreadID) { - outHilbertLUT[tid] = HilbertIndex(tid.x, tid.y); -} \ No newline at end of file diff --git a/features/Screen Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl b/features/Screen Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl index 213fadce4..c8f6b42c0 100644 --- a/features/Screen Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl +++ b/features/Screen Space GI/Shaders/ScreenSpaceGI/radianceDisocc.cs.hlsl @@ -16,7 +16,7 @@ RWTexture2D outRadianceDisocc : register(u0); RWTexture2D outAccumFrames : register(u1); RWTexture2D outRemappedPrevGI : register(u2); -#if (defined(GI) && defined(GI_BOUNCE)) || defined(TEMPORAL_DENOISER) +#if (defined(GI) && defined(GI_BOUNCE)) || defined(TEMPORAL_DENOISER) || defined(HALF_RATE) # define REPROJECTION #endif @@ -46,7 +46,7 @@ void readHistory( // bool normal_pass = normal_prod * normal_prod > NormalDisocclusion; if (depth_pass) { #if defined(GI) && defined(GI_BOUNCE) - prev_gi_albedo += FULLRES_LOAD(srcPrevAmbient, pixCoord, uv * srcScale, samplerLinearClamp) * bilinear_weight; // TODO better half res + prev_gi_albedo += srcPrevAmbient[pixCoord] * bilinear_weight; // TODO better half res #endif #ifdef TEMPORAL_DENOISER prev_gi += srcPrevGI[pixCoord] * bilinear_weight; @@ -67,7 +67,7 @@ void readHistory( float2 prev_uv = uv; #ifdef REPROJECTION - prev_uv += FULLRES_LOAD(srcMotionVec, pixCoord, uv * srcScale, samplerLinearClamp).xy; + prev_uv += srcMotionVec[pixCoord].xy; #endif float2 prev_screen_pos = ConvertFromStereoUV(prev_uv, eyeIndex); @@ -76,10 +76,10 @@ void readHistory( float accum_frames = 0; float wsum = 0; - const float curr_depth = READ_DEPTH(srcCurrDepth, pixCoord); + const float curr_depth = srcCurrDepth[pixCoord]; #ifdef REPROJECTION if ((curr_depth <= DepthFadeRange.y) && !(any(prev_screen_pos < 0) || any(prev_screen_pos > 1))) { - // float3 curr_normal = DecodeNormal(FULLRES_LOAD(srcCurrNormal, pixCoord, uv * srcScale, samplerLinearClamp).xy); + // float3 curr_normal = DecodeNormal(srcCurrNormal[pixCoord]; // curr_normal = ViewToWorldVector(curr_normal, CameraViewInverse[eyeIndex]); float3 curr_pos = ScreenToViewPosition(screen_pos, curr_depth, eyeIndex); curr_pos = ViewToWorldPosition(curr_pos, CameraViewInverse[eyeIndex]); @@ -127,7 +127,7 @@ void readHistory( half3 radiance = 0; #ifdef GI - radiance = FULLRES_LOAD(srcDiffuse, pixCoord, uv * srcScale, samplerLinearClamp).rgb; + radiance = srcDiffuse[pixCoord].rgb; # ifdef GI_BOUNCE radiance += prev_gi_albedo.rgb * GIBounceFade; # endif diff --git a/src/Features/ScreenSpaceGI.cpp b/src/Features/ScreenSpaceGI.cpp index 96635554d..ff797bffd 100644 --- a/src/Features/ScreenSpaceGI.cpp +++ b/src/Features/ScreenSpaceGI.cpp @@ -104,7 +104,7 @@ void ScreenSpaceGI::DrawSettings() ImGui::SliderInt("Steps Per Slice", (int*)&settings.NumSteps, 1, 20); if (auto _tt = Util::HoverTooltipWrapper()) - ImGui::Text("How many samples does it take in one direction. A greater value enhances the effects but is more expensive."); + ImGui::Text("How many samples does it take in one direction. A greater value enhances accuracy but is more expensive."); if (showAdvanced) { ImGui::SliderFloat("MIP Sampling Offset", &settings.DepthMIPSamplingOffset, 2.f, 6.f, "%.2f"); @@ -112,7 +112,9 @@ void ScreenSpaceGI::DrawSettings() ImGui::Text("Mainly performance (texture memory bandwidth) setting but as a side-effect reduces overshadowing by thin objects and increases temporal instability."); } - recompileFlag |= ImGui::Checkbox("Half Resolution", &settings.HalfRes); + recompileFlag |= ImGui::Checkbox("Half Rate", &settings.HalfRate); + if (auto _tt = Util::HoverTooltipWrapper()) + ImGui::Text("Shading only half the pixels per frame. Cheaper but has more ghosting, and takes twice as long to converge."); /////////////////////////////// ImGui::SeparatorText("Visual"); @@ -122,7 +124,6 @@ void ScreenSpaceGI::DrawSettings() { auto _ = DisableGuard(!settings.EnableGI); ImGui::SliderFloat("GI Strength", &settings.GIStrength, 0.f, 20.f, "%.2f"); - // percentageSlider("GI Saturation", &settings.GISaturation); } ImGui::Separator(); @@ -177,17 +178,21 @@ void ScreenSpaceGI::DrawSettings() ImGui::Separator(); } - recompileFlag |= ImGui::Checkbox("GI Bounce", &settings.EnableGIBounce); + recompileFlag |= ImGui::Checkbox("Ambient Bounce", &settings.EnableGIBounce); if (auto _tt = Util::HoverTooltipWrapper()) - ImGui::Text("Simulates multiple light bounces. Better with denoiser on."); + ImGui::Text( + "Simulates multiple light bounces. Better with denoiser on.\n" + "Mandatory if you want ambient as part of the light source for GI calculation."); { auto __ = DisableGuard(!settings.EnableGIBounce); ImGui::Indent(); - percentageSlider("GI Bounce Strength", &settings.GIBounceFade); + percentageSlider("Ambient Bounce Strength", &settings.GIBounceFade); ImGui::Unindent(); if (auto _tt = Util::HoverTooltipWrapper()) - ImGui::Text("How much of this frame's GI gets carried to the next frame."); + ImGui::Text( + "How much of this frame's ambient+GI get carried to the next frame as source.\n" + "If you have a very high GI strength, you may want to turn this down to prevent feedback loops that bleaches everything."); } if (showAdvanced) { @@ -278,7 +283,7 @@ void ScreenSpaceGI::DrawSettings() static float debugRescale = .3f; ImGui::SliderFloat("View Resize", &debugRescale, 0.f, 1.f); - //BUFFER_VIEWER_NODE(texHilbertLUT, debugRescale) + BUFFER_VIEWER_NODE(texNoise, debugRescale) BUFFER_VIEWER_NODE(texWorkingDepth, debugRescale) BUFFER_VIEWER_NODE(texPrevGeo, debugRescale) BUFFER_VIEWER_NODE(texRadiance, debugRescale) @@ -341,12 +346,6 @@ void ScreenSpaceGI::SetupResources() .Texture2D = { .MipSlice = 0 } }; - { - texHilbertLUT = eastl::make_unique(texDesc); - texHilbertLUT->CreateSRV(srvDesc); - texHilbertLUT->CreateUAV(uavDesc); - } - auto mainTex = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kMAIN]; mainTex.texture->GetDesc(&texDesc); srvDesc.Format = uavDesc.Format = texDesc.Format = DXGI_FORMAT_R11G11B10_FLOAT; @@ -405,6 +404,40 @@ void ScreenSpaceGI::SetupResources() } } + logger::debug("Loading noise texture..."); + { + DirectX::ScratchImage image; + try { + std::filesystem::path path{ "Data\\Shaders\\ScreenSpaceGI\\fast_2uges.dds" }; + + DX::ThrowIfFailed(LoadFromDDSFile(path.c_str(), DirectX::DDS_FLAGS_NONE, nullptr, image)); + } catch (const DX::com_exception& e) { + logger::error("{}", e.what()); + return; + } + + ID3D11Resource* pResource = nullptr; + try { + DX::ThrowIfFailed(CreateTexture(device, + image.GetImages(), image.GetImageCount(), + image.GetMetadata(), &pResource)); + } catch (const DX::com_exception& e) { + logger::error("{}", e.what()); + return; + } + + texNoise = eastl::make_unique(reinterpret_cast(pResource)); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = { + .Format = texNoise->desc.Format, + .ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D, + .Texture2D = { + .MostDetailedMip = 0, + .MipLevels = 1 } + }; + texNoise->CreateSRV(srvDesc); + } + logger::debug("Creating samplers..."); { D3D11_SAMPLER_DESC samplerDesc = { @@ -428,7 +461,7 @@ void ScreenSpaceGI::SetupResources() void ScreenSpaceGI::ClearShaderCache() { static const std::vector*> shaderPtrs = { - &hilbertLutCompute, &prefilterDepthsCompute, &radianceDisoccCompute, &giCompute, &blurCompute, &upsampleCompute + &prefilterDepthsCompute, &radianceDisoccCompute, &giCompute, &blurCompute }; for (auto shader : shaderPtrs) @@ -451,18 +484,16 @@ void ScreenSpaceGI::CompileComputeShaders() std::vector shaderInfos = { - { &hilbertLutCompute, "hilbert.cs.hlsl", {} }, { &prefilterDepthsCompute, "prefilterDepths.cs.hlsl", {} }, { &radianceDisoccCompute, "radianceDisocc.cs.hlsl", {} }, { &giCompute, "gi.cs.hlsl", {} }, - { &blurCompute, "blur.cs.hlsl", {} }, - { &upsampleCompute, "upsample.cs.hlsl", {} } + { &blurCompute, "blur.cs.hlsl", {} } }; for (auto& info : shaderInfos) { if (REL::Module::IsVR()) info.defines.push_back({ "VR", "" }); - if (settings.HalfRes) - info.defines.push_back({ "HALF_RES", "" }); + if (settings.HalfRate) + info.defines.push_back({ "HALF_RATE", "" }); if (settings.EnableTemporalDenoiser) info.defines.push_back({ "TEMPORAL_DENOISER", "" }); if (settings.UseBitmask) @@ -481,30 +512,12 @@ void ScreenSpaceGI::CompileComputeShaders() info.programPtr->attach(rawPtr); } - hilbertLutGenFlag = true; recompileFlag = false; } bool ScreenSpaceGI::ShadersOK() { - return hilbertLutCompute && prefilterDepthsCompute && radianceDisoccCompute && giCompute && blurCompute && upsampleCompute; -} - -void ScreenSpaceGI::GenerateHilbertLUT() -{ - auto& context = State::GetSingleton()->context; - - ID3D11UnorderedAccessView* uav = texHilbertLUT->uav.get(); - context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr); - context->CSSetShader(hilbertLutCompute.get(), nullptr, 0); - - context->Dispatch(2, 2, 1); - - uav = nullptr; - context->CSSetUnorderedAccessViews(0, 1, &uav, nullptr); - context->CSSetShader(nullptr, nullptr, 0); - - hilbertLutGenFlag = false; + return prefilterDepthsCompute && radianceDisoccCompute && giCompute && blurCompute; } void ScreenSpaceGI::UpdateSB() @@ -514,8 +527,6 @@ void ScreenSpaceGI::UpdateSB() float2 res = { (float)texRadiance->desc.Width, (float)texRadiance->desc.Height }; float2 dynres = res * viewport->GetRuntimeData().dynamicResolutionCurrentWidthScale; dynres = { floor(dynres.x), floor(dynres.y) }; - float2 halfres = dynres * 0.5; - halfres = { floor(halfres.x), floor(halfres.y) }; static float4x4 prevInvView[2] = {}; @@ -537,8 +548,8 @@ void ScreenSpaceGI::UpdateSB() data.RcpTexDim = float2(1.0f) / res; data.SrcFrameDim = dynres; data.RcpSrcFrameDim = float2(1.0f) / dynres; - data.OutFrameDim = settings.HalfRes ? halfres : dynres; - data.RcpOutFrameDim = float2(1.0f) / (settings.HalfRes ? halfres : dynres); + data.OutFrameDim = dynres; + data.RcpOutFrameDim = float2(1.0f) / dynres; data.FrameIndex = viewport->uiFrameCount; data.NumSlices = settings.NumSlices; @@ -590,9 +601,6 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) if (recompileFlag) ClearShaderCache(); - if (hilbertLutGenFlag) - GenerateHilbertLUT(); - UpdateSB(); ////////////////////////////////////////////////////// @@ -606,8 +614,6 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) (uint)(State::GetSingleton()->screenWidth * viewport->GetRuntimeData().dynamicResolutionCurrentWidthScale), (uint)(State::GetSingleton()->screenHeight * viewport->GetRuntimeData().dynamicResolutionCurrentWidthScale) }; - uint halfRes[2] = { resolution[0] >> 1, resolution[1] >> 1 }; - auto targetRes = settings.HalfRes ? halfRes : resolution; std::array srvs = { nullptr }; std::array uavs = { nullptr }; @@ -658,7 +664,7 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) context->CSSetShaderResources(0, (uint)srvs.size(), srvs.data()); context->CSSetUnorderedAccessViews(0, (uint)uavs.size(), uavs.data(), nullptr); context->CSSetShader(radianceDisoccCompute.get(), nullptr, 0); - context->Dispatch((targetRes[0] + 7u) >> 3, (targetRes[1] + 7u) >> 3, 1); + context->Dispatch((resolution[0] + 7u) >> 3, (resolution[1] + 7u) >> 3, 1); context->GenerateMips(texRadiance->srv.get()); @@ -672,7 +678,7 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) srvs.at(0) = texWorkingDepth->srv.get(); srvs.at(1) = rts[NORMALROUGHNESS].SRV; srvs.at(2) = texRadiance->srv.get(); - srvs.at(3) = texHilbertLUT->srv.get(); + srvs.at(3) = texNoise->srv.get(); srvs.at(4) = texAccumFrames[lastFrameAccumTexIdx]->srv.get(); srvs.at(5) = texGI[inputGITexIdx]->srv.get(); @@ -683,7 +689,7 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) context->CSSetShaderResources(0, (uint)srvs.size(), srvs.data()); context->CSSetUnorderedAccessViews(0, (uint)uavs.size(), uavs.data(), nullptr); context->CSSetShader(giCompute.get(), nullptr, 0); - context->Dispatch((targetRes[0] + 7u) >> 3, (targetRes[1] + 7u) >> 3, 1); + context->Dispatch((resolution[0] + 7u) >> 3, (resolution[1] + 7u) >> 3, 1); inputGITexIdx = !inputGITexIdx; lastFrameGITexIdx = inputGITexIdx; @@ -704,7 +710,7 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) context->CSSetShaderResources(0, (uint)srvs.size(), srvs.data()); context->CSSetUnorderedAccessViews(0, (uint)uavs.size(), uavs.data(), nullptr); context->CSSetShader(blurCompute.get(), nullptr, 0); - context->Dispatch((targetRes[0] + 7u) >> 3, (targetRes[1] + 7u) >> 3, 1); + context->Dispatch((resolution[0] + 7u) >> 3, (resolution[1] + 7u) >> 3, 1); inputGITexIdx = !inputGITexIdx; lastFrameGITexIdx = inputGITexIdx; @@ -712,22 +718,6 @@ void ScreenSpaceGI::DrawSSGI(Texture2D* srcPrevAmbient) } } - // upsasmple - if (settings.HalfRes) { - resetViews(); - srvs.at(0) = texWorkingDepth->srv.get(); - srvs.at(1) = texGI[inputGITexIdx]->srv.get(); - - uavs.at(0) = texGI[!inputGITexIdx]->uav.get(); - - context->CSSetShaderResources(0, (uint)srvs.size(), srvs.data()); - context->CSSetUnorderedAccessViews(0, (uint)uavs.size(), uavs.data(), nullptr); - context->CSSetShader(upsampleCompute.get(), nullptr, 0); - context->Dispatch((resolution[0] + 7u) >> 3, (resolution[1] + 7u) >> 3, 1); - - inputGITexIdx = !inputGITexIdx; - } - outputGIIdx = inputGITexIdx; // cleanup diff --git a/src/Features/ScreenSpaceGI.h b/src/Features/ScreenSpaceGI.h index a3017ae88..f7638e5de 100644 --- a/src/Features/ScreenSpaceGI.h +++ b/src/Features/ScreenSpaceGI.h @@ -29,12 +29,10 @@ struct ScreenSpaceGI : Feature virtual inline void Draw(const RE::BSShader*, const uint32_t) override{}; void DrawSSGI(Texture2D* srcPrevAmbient); - void GenerateHilbertLUT(); void UpdateSB(); ////////////////////////////////////////////////////////////////////////////////// - bool hilbertLutGenFlag = false; bool recompileFlag = false; uint outputGIIdx = 0; @@ -44,12 +42,12 @@ struct ScreenSpaceGI : Feature bool UseBitmask = true; bool EnableGI = true; // performance/quality - uint NumSlices = 2; - uint NumSteps = 5; - bool HalfRes = true; + uint NumSlices = 1; + uint NumSteps = 4; + bool HalfRate = true; float DepthMIPSamplingOffset = 3.3f; // visual - float EffectRadius = 500.f; + float EffectRadius = 400.f; float EffectFalloffRange = .615f; float ThinOccluderCompensation = 0.f; float Thickness = 75.f; @@ -63,7 +61,7 @@ struct ScreenSpaceGI : Feature float GICompensationMaxDist = 500; // mix float AOPower = 1.f; - float GIStrength = 4.f; + float GIStrength = 6.f; // denoise bool EnableTemporalDenoiser = true; bool EnableBlur = true; @@ -119,7 +117,7 @@ struct ScreenSpaceGI : Feature }; eastl::unique_ptr ssgiCB; - eastl::unique_ptr texHilbertLUT = nullptr; + eastl::unique_ptr texNoise = nullptr; eastl::unique_ptr texWorkingDepth = nullptr; winrt::com_ptr uavWorkingDepth[5] = { nullptr }; eastl::unique_ptr texPrevGeo = nullptr; @@ -130,10 +128,8 @@ struct ScreenSpaceGI : Feature winrt::com_ptr linearClampSampler = nullptr; winrt::com_ptr pointClampSampler = nullptr; - winrt::com_ptr hilbertLutCompute = nullptr; winrt::com_ptr prefilterDepthsCompute = nullptr; winrt::com_ptr radianceDisoccCompute = nullptr; winrt::com_ptr giCompute = nullptr; winrt::com_ptr blurCompute = nullptr; - winrt::com_ptr upsampleCompute = nullptr; }; \ No newline at end of file