added screen space contact shadows

This commit is contained in:
Turanszki Janos
2021-01-28 01:09:25 +01:00
parent 6bc3ae1974
commit 961414186b
23 changed files with 469 additions and 53 deletions
+31 -1
View File
@@ -11,7 +11,7 @@ using namespace wiGraphics;
void PostprocessWindow::Create(EditorComponent* editor)
{
wiWindow::Create("PostProcess Window");
SetSize(XMFLOAT2(420, 500));
SetSize(XMFLOAT2(420, 520));
float x = 150;
float y = 10;
@@ -156,6 +156,36 @@ void PostprocessWindow::Create(EditorComponent* editor)
AddWidget(&raytracedReflectionsCheckBox);
raytracedReflectionsCheckBox.SetEnabled(wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING));
screenSpaceShadowsCheckBox.Create("SS Shadows: ");
screenSpaceShadowsCheckBox.SetTooltip("Enable screen space contact shadows. This can add small shadows details to shadow maps in screen space.");
screenSpaceShadowsCheckBox.SetSize(XMFLOAT2(hei, hei));
screenSpaceShadowsCheckBox.SetPos(XMFLOAT2(x, y += step));
screenSpaceShadowsCheckBox.SetCheck(wiRenderer::GetScreenSpaceShadowsEnabled());
screenSpaceShadowsCheckBox.OnClick([=](wiEventArgs args) {
wiRenderer::SetScreenSpaceShadowsEnabled(args.bValue);
});
AddWidget(&screenSpaceShadowsCheckBox);
screenSpaceShadowsRangeSlider.Create(0.1f, 10.0f, 1, 1000, "Range: ");
screenSpaceShadowsRangeSlider.SetTooltip("Range of contact shadows");
screenSpaceShadowsRangeSlider.SetSize(XMFLOAT2(100, hei));
screenSpaceShadowsRangeSlider.SetPos(XMFLOAT2(x + 100, y));
screenSpaceShadowsRangeSlider.SetValue((float)editor->renderPath->getScreenSpaceShadowRange());
screenSpaceShadowsRangeSlider.OnSlide([=](wiEventArgs args) {
editor->renderPath->setScreenSpaceShadowRange(args.fValue);
});
AddWidget(&screenSpaceShadowsRangeSlider);
screenSpaceShadowsStepCountSlider.Create(4, 128, 16, 128 - 4, "Sample Count: ");
screenSpaceShadowsStepCountSlider.SetTooltip("Sample count of contact shadows. Higher values are better quality but slower.");
screenSpaceShadowsStepCountSlider.SetSize(XMFLOAT2(100, hei));
screenSpaceShadowsStepCountSlider.SetPos(XMFLOAT2(x + 100, y += step));
screenSpaceShadowsStepCountSlider.SetValue((float)editor->renderPath->getScreenSpaceShadowSampleCount());
screenSpaceShadowsStepCountSlider.OnSlide([=](wiEventArgs args) {
editor->renderPath->setScreenSpaceShadowSampleCount(args.iValue);
});
AddWidget(&screenSpaceShadowsStepCountSlider);
eyeAdaptionCheckBox.Create("EyeAdaption: ");
eyeAdaptionCheckBox.SetTooltip("Enable eye adaption for the overall screen luminance");
eyeAdaptionCheckBox.SetSize(XMFLOAT2(hei, hei));
+3
View File
@@ -18,6 +18,9 @@ public:
wiSlider aoSampleCountSlider;
wiCheckBox ssrCheckBox;
wiCheckBox raytracedReflectionsCheckBox;
wiCheckBox screenSpaceShadowsCheckBox;
wiSlider screenSpaceShadowsStepCountSlider;
wiSlider screenSpaceShadowsRangeSlider;
wiCheckBox eyeAdaptionCheckBox;
wiCheckBox motionBlurCheckBox;
wiSlider motionBlurStrengthSlider;
+15 -2
View File
@@ -151,7 +151,6 @@ void RenderPath3D::ResizeBuffers()
device->CreateTexture(&desc, nullptr, &rtAO);
device->SetName(&rtAO, "rtAO");
}
if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING))
{
TextureDesc desc;
desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS;
@@ -844,6 +843,19 @@ void RenderPath3D::Render() const
RenderSSR(cmd);
if (wiRenderer::GetScreenSpaceShadowsEnabled())
{
wiRenderer::Postprocess_ScreenSpaceShadow(
depthBuffer_Copy,
rtLinearDepth,
entityTiles_Opaque,
rtShadow,
cmd,
getScreenSpaceShadowRange(),
getScreenSpaceShadowSampleCount()
);
}
if (wiRenderer::GetRaytracedShadowsEnabled())
{
wiRenderer::Postprocess_RTShadow(
@@ -857,6 +869,7 @@ void RenderPath3D::Render() const
cmd
);
}
});
// Opaque scene:
@@ -875,7 +888,7 @@ void RenderPath3D::Render() const
vp.Height = (float)depthBuffer_Main.GetDesc().Height;
device->BindViewports(1, &vp, cmd);
if (wiRenderer::GetRaytracedShadowsEnabled())
if (wiRenderer::GetRaytracedShadowsEnabled() || wiRenderer::GetScreenSpaceShadowsEnabled())
{
device->BindResource(PS, &rtShadow, TEXSLOT_RENDERPATH_RTSHADOW, cmd);
}
+6
View File
@@ -35,6 +35,8 @@ private:
uint32_t aoSampleCount = 16;
float aoPower = 2.0f;
float chromaticAberrationAmount = 2.0f;
uint32_t screenSpaceShadowSampleCount = 16;
float screenSpaceShadowRange = 1;
AO ao = AO_DISABLED;
bool fxaaEnabled = false;
@@ -179,6 +181,8 @@ public:
constexpr uint32_t getAOSampleCount() const { return aoSampleCount; }
constexpr float getAOPower() const { return aoPower; }
constexpr float getChromaticAberrationAmount() const { return chromaticAberrationAmount; }
constexpr uint32_t getScreenSpaceShadowSampleCount() const { return screenSpaceShadowSampleCount; }
constexpr float getScreenSpaceShadowRange() const { return screenSpaceShadowRange; }
constexpr bool getAOEnabled() const { return ao != AO_DISABLED; }
constexpr AO getAO() const { return ao; }
@@ -219,6 +223,8 @@ public:
constexpr void setAOSampleCount(uint32_t value) { aoSampleCount = value; }
constexpr void setAOPower(float value) { aoPower = value; }
constexpr void setChromaticAberrationAmount(float value) { chromaticAberrationAmount = value; }
constexpr void setScreenSpaceShadowSampleCount(uint32_t value) { screenSpaceShadowSampleCount = value; }
constexpr void setScreenSpaceShadowRange(float value) { screenSpaceShadowRange = value; }
constexpr void setAO(AO value) { ao = value; }
constexpr void setSSREnabled(bool value){ ssrEnabled = value; }
+1
View File
@@ -234,6 +234,7 @@ static const uint OPTION_BIT_SIMPLE_SKY = 1 << 5;
static const uint OPTION_BIT_REALISTIC_SKY = 1 << 6;
static const uint OPTION_BIT_RAYTRACED_SHADOWS = 1 << 7;
static const uint OPTION_BIT_DISABLE_ALBEDO_MAPS = 1 << 8;
static const uint OPTION_BIT_SHADOW_MASK = 1 << 9;
// ---------- Common Constant buffers: -----------------
+10
View File
@@ -869,6 +869,16 @@
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Compute</ShaderType>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)screenspaceshadowCS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Compute</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Compute</ShaderType>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)skyPS_velocity.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Pixel</ShaderType>
@@ -956,5 +956,8 @@
<FxCompile Include="$(MSBuildThisFileDirectory)objectDS_prepass_alphatest.hlsl">
<Filter>DS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)screenspaceshadowCS.hlsl">
<Filter>CS</Filter>
</FxCompile>
</ItemGroup>
</Project>
+3 -3
View File
@@ -1,6 +1,6 @@
#define DISABLE_DECALS
#define DISABLE_ENVMAPS
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#include "globals.hlsli"
#include "objectHF.hlsli"
#include "hairparticleHF.hlsli"
@@ -30,13 +30,13 @@ GBuffer main(VertexToPixel input)
Lighting lighting;
lighting.create(0, 0, GetAmbient(surface.N), 0);
#ifdef RAYTRACED_SHADOWS_ENABLED
#ifdef SHADOW_MASK_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS)
{
lighting.shadow_mask = texture_rtshadow[surface.pixel];
}
#endif // RAYTRACED_SHADOWS_ENABLED
#endif // SHADOW_MASK_ENABLED
float depth = input.pos.z;
float3 reflection = 0;
+39 -33
View File
@@ -186,21 +186,12 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li
[branch]
if (light.IsCastingShadow())
{
#ifdef RAYTRACED_SHADOWS_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS)
{
#ifdef RAYTRACING_INLINE
shadow *= shadowTrace(surface, normalize(L), FLT_MAX);
#else
uint mask_shift = (lighting.shadow_index % 4) * 8;
uint mask_bucket = lighting.shadow_index / 4;
uint mask = (lighting.shadow_mask[mask_bucket] >> mask_shift) & 0xFF;
shadow = mask / 255.0;
#endif // RAYTRACING_INLINE
}
else
#endif // RAYTRACED_SHADOWS_ENABLED
{
// Loop through cascades from closest (smallest) to furthest (biggest)
[loop]
@@ -238,6 +229,17 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li
}
}
}
#ifdef SHADOW_MASK_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_SHADOW_MASK)
{
uint mask_shift = (lighting.shadow_index % 4) * 8;
uint mask_bucket = lighting.shadow_index / 4;
uint mask = (lighting.shadow_mask[mask_bucket] >> mask_shift) & 0xFF;
shadow *= mask / 255.0;
}
#endif // SHADOW_MASK_ENABLED
}
[branch]
@@ -260,7 +262,7 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li
}
}
#ifdef RAYTRACED_SHADOWS_ENABLED
#ifdef SHADOW_MASK_ENABLED
#ifndef RAYTRACING_INLINE
[branch]
if (light.IsCastingShadow())
@@ -274,7 +276,7 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li
lighting.shadow_index++;
}
#endif // RAYTRACING_INLINE
#endif // RAYTRACED_SHADOWS_ENABLED
#endif // SHADOW_MASK_ENABLED
}
inline void PointLight(in ShaderEntity light, in Surface surface, inout Lighting lighting)
{
@@ -300,24 +302,26 @@ inline void PointLight(in ShaderEntity light, in Surface surface, inout Lighting
[branch]
if (light.IsCastingShadow())
{
#ifdef RAYTRACED_SHADOWS_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS)
{
#ifdef RAYTRACING_INLINE
shadow *= shadowTrace(surface, L, dist);
#else
uint mask_shift = (lighting.shadow_index % 4) * 8;
uint mask_bucket = lighting.shadow_index / 4;
uint mask = (lighting.shadow_mask[mask_bucket] >> mask_shift) & 0xFF;
shadow = mask / 255.0;
#endif // RAYTRACING_INLINE
}
else
#endif // RAYTRACED_SHADOWS_ENABLED
{
shadow *= shadowCube(light, L, Lunnormalized);
}
#ifdef SHADOW_MASK_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_SHADOW_MASK)
{
uint mask_shift = (lighting.shadow_index % 4) * 8;
uint mask_bucket = lighting.shadow_index / 4;
uint mask = (lighting.shadow_mask[mask_bucket] >> mask_shift) & 0xFF;
shadow *= mask / 255.0;
}
#endif // SHADOW_MASK_ENABLED
}
[branch]
@@ -338,7 +342,7 @@ inline void PointLight(in ShaderEntity light, in Surface surface, inout Lighting
}
}
#ifdef RAYTRACED_SHADOWS_ENABLED
#ifdef SHADOW_MASK_ENABLED
#ifndef RAYTRACING_INLINE
[branch]
if (light.IsCastingShadow())
@@ -352,7 +356,7 @@ inline void PointLight(in ShaderEntity light, in Surface surface, inout Lighting
lighting.shadow_index++;
}
#endif // RAYTRACING_INLINE
#endif // RAYTRACED_SHADOWS_ENABLED
#endif // SHADOW_MASK_ENABLED
}
inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting lighting)
{
@@ -383,21 +387,12 @@ inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting
[branch]
if (light.IsCastingShadow())
{
#ifdef RAYTRACED_SHADOWS_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS)
{
#ifdef RAYTRACING_INLINE
shadow *= shadowTrace(surface, L, dist);
#else
uint mask_shift = (lighting.shadow_index % 4) * 8;
uint mask_bucket = lighting.shadow_index / 4;
uint mask = (lighting.shadow_mask[mask_bucket] >> mask_shift) & 0xFF;
shadow = mask / 255.0;
#endif // RAYTRACING_INLINE
}
else
#endif // RAYTRACED_SHADOWS_ENABLED
{
float4 ShPos = mul(MatrixArray[light.GetMatrixIndex() + 0], float4(surface.P, 1));
ShPos.xyz /= ShPos.w;
@@ -408,6 +403,17 @@ inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting
shadow *= shadowCascade(light, ShPos.xyz, ShTex.xy, 0);
}
}
#ifdef SHADOW_MASK_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_SHADOW_MASK)
{
uint mask_shift = (lighting.shadow_index % 4) * 8;
uint mask_bucket = lighting.shadow_index / 4;
uint mask = (lighting.shadow_mask[mask_bucket] >> mask_shift) & 0xFF;
shadow *= mask / 255.0;
}
#endif // SHADOW_MASK_ENABLED
}
[branch]
@@ -430,7 +436,7 @@ inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting
}
}
#ifdef RAYTRACED_SHADOWS_ENABLED
#ifdef SHADOW_MASK_ENABLED
#ifndef RAYTRACING_INLINE
[branch]
if (light.IsCastingShadow())
@@ -444,7 +450,7 @@ inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting
lighting.shadow_index++;
}
#endif // RAYTRACING_INLINE
#endif // RAYTRACED_SHADOWS_ENABLED
#endif // SHADOW_MASK_ENABLED
}
+3 -3
View File
@@ -1486,13 +1486,13 @@ float4 main(PixelInput input) : SV_TARGET
#endif
#ifdef RAYTRACED_SHADOWS_ENABLED
#ifdef SHADOW_MASK_ENABLED
[branch]
if (g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS)
if (g_xFrame_Options & OPTION_BIT_SHADOW_MASK)
{
lighting.shadow_mask = texture_rtshadow[surface.pixel];
}
#endif // RAYTRACED_SHADOWS_ENABLED
#endif // SHADOW_MASK_ENABLED
#ifdef FORWARD
+1 -1
View File
@@ -1,6 +1,6 @@
#define OBJECTSHADER_COMPILE_PS
#define OBJECTSHADER_LAYOUT_COMMON
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#define OUTPUT_GBUFFER
#define TILEDFORWARD
#define DISABLE_ALPHATEST
+1 -1
View File
@@ -1,6 +1,6 @@
#define OBJECTSHADER_COMPILE_PS
#define OBJECTSHADER_LAYOUT_COMMON
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#define OUTPUT_GBUFFER
#define TILEDFORWARD
#define DISABLE_ALPHATEST
+1 -1
View File
@@ -1,6 +1,6 @@
#define OBJECTSHADER_COMPILE_PS
#define OBJECTSHADER_LAYOUT_COMMON
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#define OUTPUT_GBUFFER
#define TILEDFORWARD
#define DISABLE_ALPHATEST
+1 -1
View File
@@ -1,6 +1,6 @@
#define OBJECTSHADER_COMPILE_PS
#define OBJECTSHADER_LAYOUT_COMMON
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#define OUTPUT_GBUFFER
#define TILEDFORWARD
#define DISABLE_ALPHATEST
+1 -1
View File
@@ -1,6 +1,6 @@
#define OBJECTSHADER_COMPILE_PS
#define OBJECTSHADER_LAYOUT_COMMON
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#define OUTPUT_GBUFFER
#define TILEDFORWARD
#define DISABLE_ALPHATEST
+1 -1
View File
@@ -1,6 +1,6 @@
#define OBJECTSHADER_COMPILE_PS
#define OBJECTSHADER_LAYOUT_COMMON
#define RAYTRACED_SHADOWS_ENABLED
#define SHADOW_MASK_ENABLED
#define OUTPUT_GBUFFER
#define TILEDFORWARD
#define DISABLE_ALPHATEST
+4 -3
View File
@@ -48,6 +48,10 @@ void RTShadow_Raygen()
uint4 shadow_mask = 0;
uint shadow_index = 0;
RayDesc ray;
ray.TMin = 0.01;
ray.Origin = surface.P + surface.N * 0.1;
[branch]
if (g_xFrame_LightArrayCount > 0)
{
@@ -88,10 +92,7 @@ void RTShadow_Raygen()
continue; // static lights will be skipped (they are used in lightmap baking)
}
RayDesc ray;
ray.TMin = 0.01;
ray.TMax = 0;
ray.Origin = trace_bias_position(surface.P, surface.N);
float3 L;
+228
View File
@@ -0,0 +1,228 @@
#define BRDF_NDOTL_BIAS 0.1
#include "globals.hlsli"
#include "ShaderInterop_Postprocess.h"
#include "raytracingHF.hlsli"
TEXTURE2D(texture_normals, float3, TEXSLOT_ONDEMAND0);
STRUCTUREDBUFFER(EntityTiles, uint, TEXSLOT_RENDERPATH_ENTITYTILES);
static const uint MAX_RTSHADOWS = 16;
RWTEXTURE2D(output, uint4, 0);
[numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)]
void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint groupIndex : SV_GroupIndex)
{
const float2 uv = ((float2)DTid.xy + 0.5f) * xPPResolution_rcp;
const float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1);
if (depth == 0.0f)
return;
const float3 P = reconstructPosition(uv, depth);
float3 N = normalize(texture_normals.SampleLevel(sampler_point_clamp, uv, 0) * 2 - 1);
Surface surface;
surface.init();
surface.pixel = DTid.xy;
surface.P = P + N * 0.05;
surface.N = N;
const uint2 tileIndex = uint2(floor(surface.pixel * 2 / TILED_CULLING_BLOCKSIZE));
const uint flatTileIndex = flatten2D(tileIndex, g_xFrame_EntityCullingTileCount.xy) * SHADER_ENTITY_TILE_BUCKET_COUNT;
uint shadow_mask[4] = {0,0,0,0};
uint shadow_index = 0;
const float3 rayOrigin = mul(g_xCamera_View, float4(surface.P, 1)).xyz;
const float range = xPPParams0.x;
const uint samplecount = xPPParams0.y;
const float thickness = 0.1;
const float stepsize = range / samplecount;
const float offset = abs(dither(DTid.xy + GetTemporalAASampleRotation()));
[branch]
if (g_xFrame_LightArrayCount > 0)
{
// Loop through light buckets in the tile:
const uint first_item = g_xFrame_LightArrayOffset;
const uint last_item = first_item + g_xFrame_LightArrayCount - 1;
const uint first_bucket = first_item / 32;
const uint last_bucket = min(last_item / 32, max(0, SHADER_ENTITY_TILE_BUCKET_COUNT - 1));
[loop]
for (uint bucket = first_bucket; bucket <= last_bucket && shadow_index < MAX_RTSHADOWS; ++bucket)
{
uint bucket_bits = EntityTiles[flatTileIndex + bucket];
// Bucket scalarizer - Siggraph 2017 - Improved Culling [Michal Drobot]:
bucket_bits = WaveReadLaneFirst(WaveActiveBitOr(bucket_bits));
[loop]
while (bucket_bits != 0 && shadow_index < MAX_RTSHADOWS)
{
// Retrieve global entity index from local bucket, then remove bit from local bucket:
const uint bucket_bit_index = firstbitlow(bucket_bits);
const uint entity_index = bucket * 32 + bucket_bit_index;
bucket_bits ^= 1 << bucket_bit_index;
// Check if it is a light and process:
[branch]
if (entity_index >= first_item && entity_index <= last_item)
{
ShaderEntity light = EntityArray[entity_index];
if (!light.IsCastingShadow())
{
continue;
}
if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC)
{
continue; // static lights will be skipped (they are used in lightmap baking)
}
float3 L;
bool has_shadow = false;
switch (light.GetType())
{
default:
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
L = normalize(light.GetDirection());
SurfaceToLight surfaceToLight;
surfaceToLight.create(surface, L);
[branch]
if (any(surfaceToLight.NdotL))
{
[branch]
if (light.IsCastingShadow())
{
has_shadow = true;
}
}
}
break;
case ENTITY_TYPE_POINTLIGHT:
{
L = light.position - surface.P;
const float dist2 = dot(L, L);
const float range2 = light.GetRange() * light.GetRange();
[branch]
if (dist2 < range2)
{
const float3 Lunnormalized = L;
const float dist = sqrt(dist2);
L /= dist;
SurfaceToLight surfaceToLight;
surfaceToLight.create(surface, L);
[branch]
if (any(surfaceToLight.NdotL))
{
has_shadow = true;
}
}
}
break;
case ENTITY_TYPE_SPOTLIGHT:
{
L = light.position - surface.P;
const float dist2 = dot(L, L);
const float range2 = light.GetRange() * light.GetRange();
[branch]
if (dist2 < range2)
{
const float dist = sqrt(dist2);
L /= dist;
SurfaceToLight surfaceToLight;
surfaceToLight.create(surface, L);
[branch]
if (any(surfaceToLight.NdotL_sss))
{
const float SpotFactor = dot(L, light.GetDirection());
const float spotCutOff = light.GetConeAngleCos();
[branch]
if (SpotFactor > spotCutOff)
{
has_shadow = true;
}
}
}
}
break;
}
[branch]
if (has_shadow)
{
const float3 rayDirection = normalize(mul((float3x3)g_xCamera_View, L));
float3 rayPos = rayOrigin + rayDirection * stepsize * offset;
float occlusion = 0;
[loop]
for (uint i = 0; i < samplecount; ++i)
{
rayPos += rayDirection * stepsize;
float4 proj = mul(g_xCamera_Proj, float4(rayPos, 1));
proj.xyz /= proj.w;
proj.xy = proj.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f);
[branch]
if (is_saturated(proj.xy))
{
const float ray_depth_real = proj.w;
const float ray_depth_sample = texture_lineardepth.SampleLevel(sampler_point_clamp, proj.xy, 0) * g_xCamera_ZFarP;
const float ray_depth_delta = ray_depth_real - ray_depth_sample;
if (ray_depth_delta > 0 && ray_depth_delta < thickness)
{
occlusion = 1;
// screen edge fade:
float2 fade = max(12 * abs(uv - 0.5) - 5, 0);
occlusion *= saturate(1 - dot(fade, fade));
break;
}
}
}
float shadow = 1 - occlusion;
uint mask = uint(saturate(shadow) * 255); // 8 bits
uint mask_shift = (shadow_index % 4) * 8;
uint mask_bucket = shadow_index / 4;
shadow_mask[mask_bucket] |= mask << mask_shift;
}
// (**) cannot detect exactly same contribution as is pixel shaders!
// So we always increment it for shadowed light, even if the
// shadow contribution is not traced
//
// This is because in the pixel shader, we will detect the shadow
// contribution more precisely due to more precise surface normals
shadow_index++;
}
else if (entity_index > last_item)
{
// force exit:
bucket = SHADER_ENTITY_TILE_BUCKET_COUNT;
break;
}
}
}
}
output[DTid.xy] = uint4(shadow_mask[0], shadow_mask[1], shadow_mask[2], shadow_mask[3]);
}
+1
View File
@@ -377,6 +377,7 @@ enum SHADERTYPE
CSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL_UINT4,
CSTYPE_POSTPROCESS_DOWNSAMPLE4X,
CSTYPE_POSTPROCESS_NORMALSFROMDEPTH,
CSTYPE_POSTPROCESS_SCREENSPACESHADOW,
+103 -1
View File
@@ -97,6 +97,7 @@ bool raytracedShadows = false;
bool tessellationEnabled = true;
bool disableAlbedoMaps = false;
uint32_t raytracedShadowsSampleCount = 1;
bool SCREENSPACESHADOWS = false;
struct VoxelizedSceneData
@@ -1236,6 +1237,7 @@ void LoadShaders()
wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL_UINT4], "upsample_bilateral_uint4CS.cso"); });
wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_DOWNSAMPLE4X], "downsample4xCS.cso"); });
wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_NORMALSFROMDEPTH], "normalsfromdepthCS.cso"); });
wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_SCREENSPACESHADOW], "screenspaceshadowCS.cso"); });
wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(HS, shaders[HSTYPE_OBJECT], "objectHS.cso"); });
@@ -3656,11 +3658,16 @@ void UpdatePerFrameData(
if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING) && GetRaytracedShadowsEnabled())
{
frameCB.g_xFrame_Options |= OPTION_BIT_RAYTRACED_SHADOWS;
frameCB.g_xFrame_Options |= OPTION_BIT_SHADOW_MASK;
}
if (disableAlbedoMaps)
if (IsDisableAlbedoMaps())
{
frameCB.g_xFrame_Options |= OPTION_BIT_DISABLE_ALBEDO_MAPS;
}
if (GetScreenSpaceShadowsEnabled())
{
frameCB.g_xFrame_Options |= OPTION_BIT_SHADOW_MASK;
}
}
void UpdateRenderData(
const Visibility& vis,
@@ -10472,6 +10479,93 @@ void Postprocess_RTShadow(
wiProfiler::EndRange(prof_range);
device->EventEnd(cmd);
}
void Postprocess_ScreenSpaceShadow(
const Texture& depthbuffer,
const Texture& lineardepth,
const GPUBuffer& entityTiles_Opaque,
const Texture& output,
CommandList cmd,
float range,
uint32_t samplecount
)
{
device->EventBegin("Postprocess_ScreenSpaceShadow", cmd);
auto prof_range = wiProfiler::BeginRangeGPU("ScreenSpaceShadow", cmd);
static TextureDesc saved_desc;
static Texture temp;
static Texture temporal[2];
static Texture normals;
const TextureDesc& lineardepth_desc = lineardepth.GetDesc();
if (saved_desc.Width != lineardepth_desc.Width || saved_desc.Height != lineardepth_desc.Height)
{
saved_desc = lineardepth_desc; // <- this must already have SRV and UAV request flags set up!
saved_desc.MipLevels = 1;
TextureDesc desc = saved_desc;
desc.Width = (desc.Width + 1) / 2;
desc.Height = (desc.Height + 1) / 2;
desc.Format = FORMAT_R32G32B32A32_UINT;
device->CreateTexture(&desc, nullptr, &temp);
device->SetName(&temp, "rtshadow_temp");
device->CreateTexture(&desc, nullptr, &temporal[0]);
device->SetName(&temporal[0], "rtshadow_temporal[0]");
device->CreateTexture(&desc, nullptr, &temporal[1]);
device->SetName(&temporal[1], "rtshadow_temporal[1]");
desc.Format = FORMAT_R11G11B10_FLOAT;
device->CreateTexture(&desc, nullptr, &normals);
device->SetName(&normals, "rtshadow_normals");
}
Postprocess_NormalsFromDepth(depthbuffer, normals, cmd);
const TextureDesc& desc = temp.GetDesc();
PostProcessCB cb;
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;
cb.xPPParams0.x = range;
cb.xPPParams0.y = (float)samplecount;
device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd);
device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd);
device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SCREENSPACESHADOW], cmd);
device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd);
device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd);
device->BindResource(CS, &normals, TEXSLOT_ONDEMAND0, cmd);
device->BindResource(CS, &entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd);
const GPUResource* uavs[] = {
&temp,
};
device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd);
device->Dispatch(
(desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE,
(desc.Height + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE,
1,
cmd
);
GPUBarrier barriers[] = {
GPUBarrier::Memory(),
};
device->Barrier(barriers, arraysize(barriers), cmd);
device->UnbindUAVs(0, arraysize(uavs), cmd);
Postprocess_Upsample_Bilateral(temp, lineardepth, output, cmd);
wiProfiler::EndRange(prof_range);
device->EventEnd(cmd);
}
void Postprocess_LightShafts(
const Texture& input,
const Texture& output,
@@ -12305,5 +12399,13 @@ uint32_t GetRaytracedShadowsSampleCount()
{
return raytracedShadowsSampleCount;
}
void SetScreenSpaceShadowsEnabled(bool value)
{
SCREENSPACESHADOWS = value;
}
bool GetScreenSpaceShadowsEnabled()
{
return SCREENSPACESHADOWS;
}
}
+11
View File
@@ -353,6 +353,15 @@ namespace wiRenderer
const wiGraphics::Texture& output,
wiGraphics::CommandList cmd
);
void Postprocess_ScreenSpaceShadow(
const wiGraphics::Texture& depthbuffer,
const wiGraphics::Texture& lineardepth,
const wiGraphics::GPUBuffer& entityTiles_Opaque,
const wiGraphics::Texture& output,
wiGraphics::CommandList cmd,
float range = 1,
uint32_t samplecount = 16
);
void Postprocess_LightShafts(
const wiGraphics::Texture& input,
const wiGraphics::Texture& output,
@@ -618,6 +627,8 @@ namespace wiRenderer
bool IsDisableAlbedoMaps();
void SetRaytracedShadowsSampleCount(uint32_t value);
uint32_t GetRaytracedShadowsSampleCount();
void SetScreenSpaceShadowsEnabled(bool value);
bool GetScreenSpaceShadowsEnabled();
const wiGraphics::Texture* GetGlobalLightmap();
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates, breaking compatibility changes
const int minor = 52;
// minor bug fixes, alterations, refactors, updates
const int revision = 13;
const int revision = 14;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
+1
View File
@@ -87,3 +87,4 @@ Springs
Terrain Rendering (material blending)
Variable Rate Shading
Real time ray tracing: ambient occlusion, shadows, reflections (DXR and Vulkan raytracing)
Screen Space Contact Shadows