diff --git a/Editor/PostprocessWindow.cpp b/Editor/PostprocessWindow.cpp index 55f70c2ab..4f0f1bea2 100644 --- a/Editor/PostprocessWindow.cpp +++ b/Editor/PostprocessWindow.cpp @@ -132,7 +132,7 @@ PostprocessWindow::PostprocessWindow(wiGUI* gui, RenderPath3D* comp) : GUI(gui), }); ppWindow->AddWidget(depthOfFieldCheckBox); - depthOfFieldFocusSlider = new wiSlider(0.01f, 600, 100, 10000, "Focus: "); + depthOfFieldFocusSlider = new wiSlider(0.1f, 100, 10, 10000, "Focus: "); depthOfFieldFocusSlider->SetTooltip("Set the focus distance from the camera. The picture will be sharper near the focus, and blurrier further from it."); depthOfFieldFocusSlider->SetScriptTip("RenderPath3D::SetDepthOfFieldFocus(float value)"); depthOfFieldFocusSlider->SetSize(XMFLOAT2(100, 20)); @@ -143,16 +143,16 @@ PostprocessWindow::PostprocessWindow(wiGUI* gui, RenderPath3D* comp) : GUI(gui), }); ppWindow->AddWidget(depthOfFieldFocusSlider); - depthOfFieldStrengthSlider = new wiSlider(0.01f, 4, 100, 1000, "Strength: "); - depthOfFieldStrengthSlider->SetTooltip("Set depth of field blur strength."); - depthOfFieldStrengthSlider->SetScriptTip("RenderPath3D::SetDepthOfFieldStrength(float value)"); - depthOfFieldStrengthSlider->SetSize(XMFLOAT2(100, 20)); - depthOfFieldStrengthSlider->SetPos(XMFLOAT2(x + 100, y += 35)); - depthOfFieldStrengthSlider->SetValue(component->getDepthOfFieldStrength()); - depthOfFieldStrengthSlider->OnSlide([&](wiEventArgs args) { + depthOfFieldScaleSlider = new wiSlider(0.01f, 4, 100, 1000, "Scale: "); + depthOfFieldScaleSlider->SetTooltip("Set depth of field scale/falloff."); + depthOfFieldScaleSlider->SetScriptTip("RenderPath3D::SetDepthOfFieldStrength(float value)"); + depthOfFieldScaleSlider->SetSize(XMFLOAT2(100, 20)); + depthOfFieldScaleSlider->SetPos(XMFLOAT2(x + 100, y += 35)); + depthOfFieldScaleSlider->SetValue(component->getDepthOfFieldStrength()); + depthOfFieldScaleSlider->OnSlide([&](wiEventArgs args) { component->setDepthOfFieldStrength(args.fValue); }); - ppWindow->AddWidget(depthOfFieldStrengthSlider); + ppWindow->AddWidget(depthOfFieldScaleSlider); bloomCheckBox = new wiCheckBox("Bloom: "); bloomCheckBox->SetTooltip("Enable bloom. The effect adds color bleeding to the brightest parts of the scene."); diff --git a/Editor/PostprocessWindow.h b/Editor/PostprocessWindow.h index 0ece1be09..bc43291c9 100644 --- a/Editor/PostprocessWindow.h +++ b/Editor/PostprocessWindow.h @@ -31,7 +31,7 @@ public: wiCheckBox* motionBlurCheckBox; wiCheckBox* depthOfFieldCheckBox; wiSlider* depthOfFieldFocusSlider; - wiSlider* depthOfFieldStrengthSlider; + wiSlider* depthOfFieldScaleSlider; wiCheckBox* bloomCheckBox; wiSlider* bloomStrengthSlider; wiCheckBox* fxaaCheckBox; diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj b/WickedEngine/WickedEngine_SHADERS.vcxproj index c4ac5d50a..f2c3e3e02 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj @@ -14,6 +14,7 @@ + @@ -119,14 +120,18 @@ Pixel - + Compute Compute 5.0 - + + Compute + 5.0 + + Compute 5.0 @@ -138,6 +143,10 @@ Compute 5.0 + + Compute + 5.0 + Pixel diff --git a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters index 07df05f8d..d5cfb300f 100644 --- a/WickedEngine/WickedEngine_SHADERS.vcxproj.filters +++ b/WickedEngine/WickedEngine_SHADERS.vcxproj.filters @@ -82,6 +82,9 @@ HF + + HF + @@ -732,9 +735,6 @@ CS - - CS - CS @@ -822,7 +822,16 @@ CS - + + CS + + + CS + + + CS + + CS diff --git a/WickedEngine/depthoffieldCS.hlsl b/WickedEngine/depthoffieldHF.hlsli similarity index 51% rename from WickedEngine/depthoffieldCS.hlsl rename to WickedEngine/depthoffieldHF.hlsli index a933a051f..f571bd644 100644 --- a/WickedEngine/depthoffieldCS.hlsl +++ b/WickedEngine/depthoffieldHF.hlsli @@ -1,13 +1,33 @@ -#include "globals.hlsli" -#include "ShaderInterop_Postprocess.h" +#ifndef WI_DEPTHOFFIELD_HF +#define WI_DEPTHOFFIELD_HF -// Implementation based on Jorge Jimenez Siggraph 2014 Next Generation Post Processing in Call of Duty Advanced Warfare -TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); -TEXTURE2D(neighborhood_mindepth_maxcoc, float2, TEXSLOT_ONDEMAND1); -TEXTURE2D(texture_presort, float4, TEXSLOT_ONDEMAND2); +#define DOF_DEPTH_SCALE_FOREGROUND (g_xCamera_ZFarP * 0.25f) +float2 DepthCmp2(float depth, float closestTileDepth) +{ + float d = DOF_DEPTH_SCALE_FOREGROUND * (depth - closestTileDepth); + float2 depthCmp; + depthCmp.x = smoothstep(0.0, 1.0, d); // Background + depthCmp.y = 1.0 - depthCmp.x; // Foreground + return depthCmp; -RWTEXTURE2D(output, float4, 0); +} + +#define DOF_SINGLE_PIXEL_RADIUS 0.7071 // length( float2(0.5, 0.5 ) ) +float SampleAlpha(float sampleCoc) +{ + return min(rcp(PI * sampleCoc * sampleCoc), rcp(PI * DOF_SINGLE_PIXEL_RADIUS * DOF_SINGLE_PIXEL_RADIUS)); +} + +#define DOF_SPREAD_TOE_POWER 2 +float SpreadToe(float offsetCoc, float spreadCmp) +{ + return offsetCoc <= 1.0 ? pow(spreadCmp, DOF_SPREAD_TOE_POWER) : spreadCmp; +} +float SpreadCmp(float offsetCoc, float sampleCoc, float pixelToSampleUnitsScale) +{ + return SpreadToe(offsetCoc, saturate(pixelToSampleUnitsScale * sampleCoc - offsetCoc + 1.0)); +} #define DOF_RING_COUNT 4 @@ -98,66 +118,4 @@ static const float3 disc[] = static const uint ringSampleCount[] = { 0, 8, 24, 48, 80 }; static const float ringNormFactor[] = { 1.0, 0.111111, 0.040000, 0.020408, 0.012346 }; - -#define DOF_SPREAD_TOE_POWER 2 -float SpreadToe(float offsetCoc, float spreadCmp) -{ - return offsetCoc <= 1.0 ? pow(spreadCmp, DOF_SPREAD_TOE_POWER) : spreadCmp; -} -float SpreadCmp(float offsetCoc, float sampleCoc, float pixelToSampleUnitsScale) -{ - return SpreadToe(offsetCoc, saturate(pixelToSampleUnitsScale * sampleCoc - offsetCoc + 1.0)); -} - -#define DOF_SINGLE_PIXEL_RADIUS 0.7071 // length( float2(0.5, 0.5 ) ) -float SampleAlpha(float sampleCoc) -{ - return min(rcp(PI * sampleCoc * sampleCoc), rcp(PI * DOF_SINGLE_PIXEL_RADIUS * DOF_SINGLE_PIXEL_RADIUS)); -} - -[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] -void main(uint3 DTid : SV_DispatchThreadID) -{ - const float maxcoc = neighborhood_mindepth_maxcoc[DTid.xy / DEPTHOFFIELD_TILESIZE].y; - - const uint ringCount = clamp(ceil(pow(maxcoc, 0.5f) * DOF_RING_COUNT), 1, DOF_RING_COUNT); - const float spreadScale = ringCount / maxcoc; - const float2 ringScale = float(ringCount) / float(DOF_RING_COUNT) * maxcoc * xPPResolution_rcp; - - const float4 center_color = input[DTid.xy]; - const float3 center_presort = texture_presort[DTid.xy].rgb; - const float center_coc = center_presort.r; - const float center_backgroundWeight = center_presort.g; - const float center_foregroundWeight = center_presort.b; - - const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; - - float4 background = center_backgroundWeight * float4(center_color.rgb, 1); - float4 foreground = center_foregroundWeight * float4(center_color.rgb, 1); - for (uint j = 0; j < ringCount; ++j) - { - for (uint i = ringSampleCount[j]; i < ringSampleCount[j + 1]; ++i) - { - const float offsetCoc = disc[i].z; - const float2 uv2 = uv + ringScale * disc[i].xy; - const float4 color = float4(input.SampleLevel(sampler_point_clamp, uv2, 0).rgb, 1); - const float3 presort = texture_presort.SampleLevel(sampler_point_clamp, uv2, 0).rgb; - const float coc = presort.r; - const float spreadCmp = SpreadCmp(offsetCoc, coc, spreadScale); - const float backgroundWeight = presort.g * spreadCmp; - const float foregroundWeight = presort.b * spreadCmp; - background += backgroundWeight * color; - foreground += foregroundWeight * color; - } - } - background.rgb *= rcp(max(0.00001, background.a)); - foreground.rgb *= rcp(max(0.00001, foreground.a)); - - float alpha = saturate(2 * ringNormFactor[ringCount] * rcp(SampleAlpha(maxcoc)) * foreground.a); - float4 color = float4(lerp(background.rgb, foreground.rgb, alpha), center_color.a); - - output[DTid.xy] = color; - //output[DTid.xy] = alpha; - //output[DTid.xy] = maxcoc; - //output[DTid.xy] = float(ringCount) / float(DOF_RING_COUNT); -} +#endif // WI_DEPTHOFFIELD_HF diff --git a/WickedEngine/depthoffield_mainCS.hlsl b/WickedEngine/depthoffield_mainCS.hlsl new file mode 100644 index 000000000..f30a4c658 --- /dev/null +++ b/WickedEngine/depthoffield_mainCS.hlsl @@ -0,0 +1,61 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" +#include "depthoffieldHF.hlsli" + +// Implementation based on Jorge Jimenez Siggraph 2014 Next Generation Post Processing in Call of Duty Advanced Warfare + +TEXTURE2D(neighborhood_mindepth_maxcoc, float2, TEXSLOT_ONDEMAND0); +TEXTURE2D(texture_presort, float3, TEXSLOT_ONDEMAND1); +TEXTURE2D(texture_prefilter, float3, TEXSLOT_ONDEMAND2); + +RWTEXTURE2D(output_main, float3, 0); +RWTEXTURE2D(output_alpha, unorm float, 1); + +[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + const float maxcoc = neighborhood_mindepth_maxcoc[2 * DTid.xy / DEPTHOFFIELD_TILESIZE].y; + + const uint ringCount = clamp(ceil(pow(maxcoc, 0.5f) * DOF_RING_COUNT), 1, DOF_RING_COUNT); + const float spreadScale = ringCount / maxcoc; + const float2 ringScale = float(ringCount) / float(DOF_RING_COUNT) * maxcoc * xPPResolution_rcp; + + const float3 center_color = texture_prefilter[DTid.xy]; + const float3 center_presort = texture_presort[DTid.xy]; + const float center_coc = center_presort.r; + const float center_backgroundWeight = center_presort.g; + const float center_foregroundWeight = center_presort.b; + + const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; + + float4 background = center_backgroundWeight * float4(center_color.rgb, 1); + float4 foreground = center_foregroundWeight * float4(center_color.rgb, 1); + for (uint j = 0; j < ringCount; ++j) + { + for (uint i = ringSampleCount[j]; i < ringSampleCount[j + 1]; ++i) + { + const float offsetCoc = disc[i].z; + const float2 uv2 = uv + ringScale * disc[i].xy; + const float4 color = float4(texture_prefilter.SampleLevel(sampler_point_clamp, uv2, 0), 1); + const float3 presort = texture_presort.SampleLevel(sampler_point_clamp, uv2, 0).rgb; + const float coc = presort.r; + const float spreadCmp = SpreadCmp(offsetCoc, coc, spreadScale); + const float backgroundWeight = presort.g * spreadCmp; + const float foregroundWeight = presort.b * spreadCmp; + background += backgroundWeight * color; + foreground += foregroundWeight * color; + } + } + background.rgb *= rcp(max(0.00001, background.a)); + foreground.rgb *= rcp(max(0.00001, foreground.a)); + + float alpha = saturate(2 * ringNormFactor[ringCount] * rcp(SampleAlpha(maxcoc)) * foreground.a); + float3 color = lerp(background.rgb, foreground.rgb, alpha); + + output_main[DTid.xy] = color; + output_alpha[DTid.xy] = alpha; + //output_main[DTid.xy] = alpha; + //output_main[DTid.xy] = maxcoc; + //output_main[DTid.xy] = float(ringCount) / float(DOF_RING_COUNT); + //output_main[DTid.xy] = center_color; +} diff --git a/WickedEngine/depthoffield_postfilterCS.hlsl b/WickedEngine/depthoffield_postfilterCS.hlsl new file mode 100644 index 000000000..df46ec8a7 --- /dev/null +++ b/WickedEngine/depthoffield_postfilterCS.hlsl @@ -0,0 +1,25 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" + +TEXTURE2D(texture_main, float3, TEXSLOT_ONDEMAND0); + +RWTEXTURE2D(output_postfilter, float3, 0); + +[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + float3 color = 0; + color += texture_main[DTid.xy + int2(-1, -1)]; + color += texture_main[DTid.xy + int2(0, -1)]; + color += texture_main[DTid.xy + int2(1, -1)]; + color += texture_main[DTid.xy + int2(-1, 0)]; + color += texture_main[DTid.xy + int2(0, 0)]; + color += texture_main[DTid.xy + int2(1, 0)]; + color += texture_main[DTid.xy + int2(-1, 1)]; + color += texture_main[DTid.xy + int2(0, 1)]; + color += texture_main[DTid.xy + int2(1, 1)]; + color /= 9.0f; + + output_postfilter[DTid.xy] = color; + //output_postfilter[DTid.xy] = texture_main[DTid.xy]; +} \ No newline at end of file diff --git a/WickedEngine/depthoffield_prepassCS.hlsl b/WickedEngine/depthoffield_prepassCS.hlsl new file mode 100644 index 000000000..9d701b552 --- /dev/null +++ b/WickedEngine/depthoffield_prepassCS.hlsl @@ -0,0 +1,44 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" +#include "depthoffieldHF.hlsli" + +TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); +TEXTURE2D(neighborhood_mindepth_maxcoc, float2, TEXSLOT_ONDEMAND1); + +RWTEXTURE2D(output_presort, float3, 0); +RWTEXTURE2D(output_prefilter, float3, 1); + +[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + const float mindepth = neighborhood_mindepth_maxcoc[2 * DTid.xy / DEPTHOFFIELD_TILESIZE].x; + const float depth0 = texture_lineardepth[2 * DTid.xy + uint2(0, 0)]; + const float depth1 = texture_lineardepth[2 * DTid.xy + uint2(1, 0)]; + const float depth2 = texture_lineardepth[2 * DTid.xy + uint2(0, 1)]; + const float depth3 = texture_lineardepth[2 * DTid.xy + uint2(1, 1)]; + const float center_depth = max(depth0, max(depth1, max(depth2, depth3))); + const float coc = dof_scale * abs(1 - dof_focus / (center_depth * g_xCamera_ZFarP)); + const float alpha = SampleAlpha(coc); + const float2 depthcmp = DepthCmp2(center_depth, mindepth); + + const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; + + output_presort[DTid.xy] = float3(coc, alpha * depthcmp.x, alpha * depthcmp.y); + + + const float2 ringScale = 2 * coc * xPPResolution_rcp; + const float3 center_color = input.SampleLevel(sampler_point_clamp, uv, 0).rgb; + float3 prefilter = center_color; + for (uint i = ringSampleCount[0]; i < ringSampleCount[1]; ++i) + { + const float offsetCoc = disc[i].z; + const float2 uv2 = uv + ringScale * disc[i].xy; + const float depth = texture_lineardepth.SampleLevel(sampler_linear_clamp, uv2, 0); + const float3 color = input.SampleLevel(sampler_point_clamp, uv2, 0).rgb; + const float weight = saturate(abs(depth - center_depth) * g_xCamera_ZFarP * 2); + prefilter += lerp(color, center_color, weight); + } + prefilter *= ringNormFactor[1]; + + output_prefilter[DTid.xy] = prefilter; +} diff --git a/WickedEngine/depthoffield_presortCS.hlsl b/WickedEngine/depthoffield_presortCS.hlsl deleted file mode 100644 index 33cbdcb43..000000000 --- a/WickedEngine/depthoffield_presortCS.hlsl +++ /dev/null @@ -1,35 +0,0 @@ -#include "globals.hlsli" -#include "ShaderInterop_Postprocess.h" - -TEXTURE2D(neighborhood_mindepth_maxcoc, float2, TEXSLOT_ONDEMAND0); - -RWTEXTURE2D(output, float4, 0); - -#define DOF_DEPTH_SCALE_FOREGROUND (g_xCamera_ZFarP * 0.25f) -float2 DepthCmp2(float depth, float closestTileDepth) -{ - float d = DOF_DEPTH_SCALE_FOREGROUND * (depth - closestTileDepth); - float2 depthCmp; - depthCmp.x = smoothstep(0.0, 1.0, d); // Background - depthCmp.y = 1.0 - depthCmp.x; // Foreground - return depthCmp; - -} - -#define DOF_SINGLE_PIXEL_RADIUS 0.7071 // length( float2(0.5, 0.5 ) ) -float SampleAlpha(float sampleCoc) -{ - return min(rcp(PI * sampleCoc * sampleCoc), rcp(PI * DOF_SINGLE_PIXEL_RADIUS * DOF_SINGLE_PIXEL_RADIUS)); -} - -[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] -void main(uint3 DTid : SV_DispatchThreadID) -{ - const float mindepth = neighborhood_mindepth_maxcoc[DTid.xy / DEPTHOFFIELD_TILESIZE].x; - const float depth = texture_lineardepth[DTid.xy]; - const float coc = dof_scale * abs(1 - dof_focus / (depth * g_xCamera_ZFarP)); - const float alpha = SampleAlpha(coc); - const float2 depthcmp = DepthCmp2(depth, mindepth); - - output[DTid.xy] = float4(coc, alpha * depthcmp.x, alpha * depthcmp.y, 1); -} diff --git a/WickedEngine/depthoffield_upsampleCS.hlsl b/WickedEngine/depthoffield_upsampleCS.hlsl new file mode 100644 index 000000000..064606991 --- /dev/null +++ b/WickedEngine/depthoffield_upsampleCS.hlsl @@ -0,0 +1,38 @@ +#include "globals.hlsli" +#include "ShaderInterop_Postprocess.h" +#include "depthoffieldHF.hlsli" + +TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); +TEXTURE2D(texture_postfilter, float3, TEXSLOT_ONDEMAND1); +TEXTURE2D(texture_alpha, float, TEXSLOT_ONDEMAND2); +TEXTURE2D(neighborhood_mindepth_maxcoc, float2, TEXSLOT_ONDEMAND3); + +RWTEXTURE2D(output, float4, 0); + +[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; + + const float center_depth = texture_lineardepth[DTid.xy]; + const float maxcoc = neighborhood_mindepth_maxcoc[DTid.xy / DEPTHOFFIELD_TILESIZE].y; + float4 fullres = input[DTid.xy]; + const float3 halfres = texture_postfilter.SampleLevel(sampler_linear_clamp, uv, 0); + const float alpha = texture_alpha.SampleLevel(sampler_linear_clamp, uv, 0); + + const float coc = dof_scale * abs(1 - dof_focus / (center_depth * g_xCamera_ZFarP)); + + const float backgroundFactor = coc; + const float foregroundFactor = maxcoc; + + const float combinedFactor = saturate(lerp(backgroundFactor, foregroundFactor, alpha)); + + float4 color = float4(lerp(fullres.rgb, halfres, combinedFactor), fullres.a); + //color = backgroundFactor; + //color = foregroundFactor; + //color = combinedFactor; + + //if (coc < 0.01) color = float4(1, 0, 0, 1); + + output[DTid.xy] = color; +} diff --git a/WickedEngine/motionblurCS.hlsl b/WickedEngine/motionblurCS.hlsl index 4c8fb74b2..65c2cf046 100644 --- a/WickedEngine/motionblurCS.hlsl +++ b/WickedEngine/motionblurCS.hlsl @@ -49,7 +49,7 @@ void main(uint3 DTid : SV_DispatchThreadID) const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; float seed = 12345; - const float2 random_direction = rand(seed, uv) * 0.5f + 0.5f; + const float random_direction = rand(seed, uv) * 0.5f + 0.5f; const float2 sampling_direction = neighborhood_velocity * random_direction * xPPResolution_rcp; diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index 520282c25..80a523534 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -302,8 +302,10 @@ enum CSTYPES CSTYPE_POSTPROCESS_DEPTHOFFIELD_TILEMAXCOC_HORIZONTAL, CSTYPE_POSTPROCESS_DEPTHOFFIELD_TILEMAXCOC_VERTICAL, CSTYPE_POSTPROCESS_DEPTHOFFIELD_NEIGHBORHOODMAXCOC, - CSTYPE_POSTPROCESS_DEPTHOFFIELD_PRESORT, - CSTYPE_POSTPROCESS_DEPTHOFFIELD, + CSTYPE_POSTPROCESS_DEPTHOFFIELD_PREPASS, + CSTYPE_POSTPROCESS_DEPTHOFFIELD_MAIN, + CSTYPE_POSTPROCESS_DEPTHOFFIELD_POSTFILTER, + CSTYPE_POSTPROCESS_DEPTHOFFIELD_UPSAMPLE, CSTYPE_POSTPROCESS_OUTLINE_FLOAT4, CSTYPE_POSTPROCESS_OUTLINE_UNORM4, CSTYPE_POSTPROCESS_MOTIONBLUR_TILEMAXVELOCITY_HORIZONTAL, diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 01a9ad8bb..39880b342 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -1381,8 +1381,10 @@ void LoadShaders() wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_TILEMAXCOC_HORIZONTAL], "depthoffield_tileMaxCOC_horizontalCS.cso"); }); wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_TILEMAXCOC_VERTICAL], "depthoffield_tileMaxCOC_verticalCS.cso"); }); wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_NEIGHBORHOODMAXCOC], "depthoffield_neighborhoodMaxCOCCS.cso"); }); - wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PRESORT], "depthoffield_presortCS.cso"); }); - wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD], "depthoffieldCS.cso"); }); + wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PREPASS], "depthoffield_prepassCS.cso"); }); + wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_MAIN], "depthoffield_mainCS.cso"); }); + wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_POSTFILTER], "depthoffield_postfilterCS.cso"); }); + wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_UPSAMPLE], "depthoffield_upsampleCS.cso"); }); wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_OUTLINE_FLOAT4], "outlineCS_float4.cso"); }); wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_OUTLINE_UNORM4], "outlineCS_unorm4.cso"); }); wiJobSystem::Execute(ctx, []{ LoadComputeShader(computeShaders[CSTYPE_POSTPROCESS_MOTIONBLUR_TILEMAXVELOCITY_HORIZONTAL], "motionblur_tileMaxVelocity_horizontalCS.cso"); }); @@ -8842,6 +8844,10 @@ void Postprocess_DepthOfField( static Texture texture_tilemax; static Texture texture_neighborhoodmax; static Texture texture_presort; + static Texture texture_prefilter; + static Texture texture_main; + static Texture texture_postfilter; + static Texture texture_alpha; if (!init) { @@ -8861,15 +8867,20 @@ void Postprocess_DepthOfField( tile_desc.Height = desc.Height; device->CreateTexture(&tile_desc, nullptr, &texture_tilemax_horizontal); } - if (texture_presort.GetDesc().Width < desc.Width || texture_presort.GetDesc().Height < desc.Height) + if (texture_presort.GetDesc().Width != desc.Width/2 || texture_presort.GetDesc().Height != desc.Height/2) { TextureDesc presort_desc; presort_desc.type = TextureDesc::TEXTURE_2D; - presort_desc.Width = desc.Width; - presort_desc.Height = desc.Height; + presort_desc.Width = desc.Width/2; + presort_desc.Height = desc.Height/2; presort_desc.Format = FORMAT_R11G11B10_FLOAT; presort_desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; device->CreateTexture(&presort_desc, nullptr, &texture_presort); + device->CreateTexture(&presort_desc, nullptr, &texture_prefilter); + device->CreateTexture(&presort_desc, nullptr, &texture_main); + device->CreateTexture(&presort_desc, nullptr, &texture_postfilter); + presort_desc.Format = FORMAT_R8_UNORM; + device->CreateTexture(&presort_desc, nullptr, &texture_alpha); } PostProcessCB cb; @@ -8949,15 +8960,28 @@ void Postprocess_DepthOfField( device->EventEnd(cmd); } - // Presort pass: - { - device->EventBegin("Presort", cmd); - device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PRESORT], cmd); + // Switch to half res: + cb.xPPResolution.x = desc.Width / 2; + cb.xPPResolution.y = desc.Height / 2; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &texture_neighborhoodmax, TEXSLOT_ONDEMAND0, cmd); + // Prepass: + { + device->EventBegin("Prepass", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PREPASS], cmd); + + const GPUResource* res[] = { + &input, + &texture_neighborhoodmax + }; + device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); const GPUResource* uavs[] = { &texture_presort, + &texture_prefilter, }; device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); @@ -8975,13 +8999,79 @@ void Postprocess_DepthOfField( // Main pass: { - device->EventBegin("DepthOfField", cmd); - device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD], cmd); + device->EventBegin("Main pass", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_MAIN], cmd); + + const GPUResource* res[] = { + &texture_neighborhoodmax, + &texture_presort, + &texture_prefilter + }; + device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + + const GPUResource* uavs[] = { + &texture_main, + &texture_alpha + }; + device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + + device->Dispatch( + (texture_main.GetDesc().Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + (texture_main.GetDesc().Height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + 1, + cmd + ); + + device->Barrier(&GPUBarrier::Memory(), 1, cmd); + device->UnbindUAVs(0, arraysize(uavs), cmd); + device->EventEnd(cmd); + } + + // Post filter: + { + device->EventBegin("Post filter", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_POSTFILTER], cmd); + + const GPUResource* res[] = { + &texture_main, + }; + device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + + const GPUResource* uavs[] = { + &texture_postfilter + }; + device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + + device->Dispatch( + (texture_postfilter.GetDesc().Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + (texture_postfilter.GetDesc().Height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, + 1, + cmd + ); + + device->Barrier(&GPUBarrier::Memory(), 1, cmd); + device->UnbindUAVs(0, arraysize(uavs), cmd); + device->EventEnd(cmd); + } + + // Switch to full res: + cb.xPPResolution.x = desc.Width; + cb.xPPResolution.y = desc.Height; + cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; + cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; + device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + + // Upsample pass: + { + device->EventBegin("Upsample pass", cmd); + device->BindComputeShader(&computeShaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_UPSAMPLE], cmd); const GPUResource* res[] = { &input, - &texture_neighborhoodmax, - &texture_presort + &texture_postfilter, + &texture_alpha, + &texture_neighborhoodmax }; device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index aae714382..e76af24d5 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wiVersion // minor features, major updates const int minor = 36; // minor bug fixes, alterations, refactors, updates - const int revision = 28; + const int revision = 29; long GetVersion()