diff --git a/WickedEngine/shaders/ShaderInterop_DDGI.h b/WickedEngine/shaders/ShaderInterop_DDGI.h index 0f634da29..82acfa95c 100644 --- a/WickedEngine/shaders/ShaderInterop_DDGI.h +++ b/WickedEngine/shaders/ShaderInterop_DDGI.h @@ -14,6 +14,7 @@ static const uint DDGI_COLOR_TEXTURE_WIDTH = DDGI_COLOR_TEXELS * DDGI_GRID_DIMEN static const uint DDGI_COLOR_TEXTURE_HEIGHT = DDGI_COLOR_TEXELS * DDGI_GRID_DIMENSIONS.z; static const uint DDGI_DEPTH_TEXTURE_WIDTH = DDGI_DEPTH_TEXELS * DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y; static const uint DDGI_DEPTH_TEXTURE_HEIGHT = DDGI_DEPTH_TEXELS * DDGI_GRID_DIMENSIONS.z; +static const float DDGI_KEEP_DISTANCE = 0.1f; // how much distance should probes keep from surfaces #define DDGI_LINEAR_BLENDING @@ -52,12 +53,32 @@ struct DDGIRayDataPacked #endif // __cplusplus }; +struct DDGIProbeOffset +{ + uint2 data; + +#ifndef __cplusplus + inline void store(float3 offset) + { + data = pack_half3(offset); + } + inline float3 load() + { + return unpack_half3(data); + } +#endif // __cplusplus +}; + #ifndef __cplusplus inline float3 ddgi_cellsize() { return GetScene().ddgi.cell_size; } +inline float3 ddgi_cellsize_rcp() +{ + return GetScene().ddgi.cell_size_rcp; +} inline float ddgi_max_distance() { return GetScene().ddgi.max_distance; @@ -77,7 +98,13 @@ inline uint ddgi_probe_index(uint3 probeCoord) } inline float3 ddgi_probe_position(uint3 probeCoord) { - return GetScene().ddgi.grid_min + probeCoord * ddgi_cellsize(); + float3 pos = GetScene().ddgi.grid_min + probeCoord * ddgi_cellsize(); + [branch] + if (GetScene().ddgi.offset_buffer >= 0) + { + pos += bindless_buffers[GetScene().ddgi.offset_buffer].Load(ddgi_probe_index(probeCoord) * sizeof(DDGIProbeOffset)).load(); + } + return pos; } inline uint2 ddgi_probe_color_pixel(uint3 probeCoord) { @@ -111,7 +138,7 @@ float3 ddgi_sample_irradiance(float3 P, float3 N) float sum_weight = 0; // alpha is how far from the floor(currentVertex) position. on [0, 1] for each axis. - float3 alpha = clamp((P - base_probe_pos) / ddgi_cellsize(), 0, 1); + float3 alpha = saturate((P - base_probe_pos) * ddgi_cellsize_rcp()); // Iterate over adjacent probe cage for (uint i = 0; i < 8; ++i) diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index 792796376..4e06cfe38 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -43,6 +43,9 @@ struct ShaderScene float max_distance; float3 grid_extents_rcp; + int offset_buffer; + + float3 cell_size_rcp; float padding0; }; DDGI ddgi; diff --git a/WickedEngine/shaders/ddgi_raytraceCS.hlsl b/WickedEngine/shaders/ddgi_raytraceCS.hlsl index b9d842188..975b4ee0a 100644 --- a/WickedEngine/shaders/ddgi_raytraceCS.hlsl +++ b/WickedEngine/shaders/ddgi_raytraceCS.hlsl @@ -39,7 +39,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn { RayDesc ray; ray.Origin = probePos; - ray.TMin = 0.0001; + ray.TMin = 0; // don't need TMin because we are not tracing from a surface ray.TMax = FLT_MAX; ray.Direction = normalize(mul(random_orientation, spherical_fibonacci(rayIndex, push.rayCount))); diff --git a/WickedEngine/shaders/ddgi_updateCS.hlsl b/WickedEngine/shaders/ddgi_updateCS.hlsl index 61f093584..36108bdc4 100644 --- a/WickedEngine/shaders/ddgi_updateCS.hlsl +++ b/WickedEngine/shaders/ddgi_updateCS.hlsl @@ -17,6 +17,7 @@ static const float WEIGHT_EPSILON = 0.0001; #ifdef DDGI_UPDATE_DEPTH static const uint THREADCOUNT = DDGI_DEPTH_RESOLUTION; RWTexture2D output : register(u0); +RWByteAddressBuffer ddgiOffsetBuffer:register(u1); #else static const uint THREADCOUNT = DDGI_COLOR_RESOLUTION; RWTexture2D output : register(u0); @@ -32,6 +33,19 @@ void main(uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex const uint3 probeCoord = ddgi_probe_coord(probeIndex); const float maxDistance = ddgi_max_distance(); +#ifdef DDGI_UPDATE_DEPTH + [branch] + if (groupIndex == 0 && push.frameIndex == 0) + { + DDGIProbeOffset ofs; + ofs.store(float3(0, 0, 0)); + ddgiOffsetBuffer.Store(probeIndex * sizeof(DDGIProbeOffset), ofs); + } + float3 probeOffset = ddgiOffsetBuffer.Load(probeIndex * sizeof(DDGIProbeOffset)).load(); + float3 probeOffsetNew = 0; + const float probeOffsetDistance = maxDistance * DDGI_KEEP_DISTANCE; +#endif // DDGI_UPDATE_DEPTH + #ifdef DDGI_UPDATE_DEPTH float2 result = 0; const uint2 pixel_topleft = ddgi_probe_depth_pixel(probeCoord); @@ -65,14 +79,19 @@ void main(uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex DDGIRayData ray = ray_cache[r]; #ifdef DDGI_UPDATE_DEPTH - float ray_probe_distance; + float depth; if (ray.depth > 0) { - ray_probe_distance = clamp(ray.depth - 0.01, 0, maxDistance); + depth = clamp(ray.depth - 0.01, 0, maxDistance); } else { - ray_probe_distance = maxDistance; + depth = maxDistance; + } + + if (depth < probeOffsetDistance) + { + probeOffsetNew -= ray.direction * (probeOffsetDistance - depth); } #else const float3 radiance = ray.radiance.rgb; @@ -86,7 +105,7 @@ void main(uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex if (weight > WEIGHT_EPSILON) { #ifdef DDGI_UPDATE_DEPTH - result += float2(ray_probe_distance * weight, sqr(ray_probe_distance) * weight); + result += float2(depth, sqr(depth)) * weight; #else result += ray.radiance.rgb * weight; #endif // DDGI_UPDATE_DEPTH @@ -129,6 +148,17 @@ void main(uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex uint2 dst_coord = copy_coord + DDGI_DEPTH_BORDER_OFFSETS[index].zw; output[dst_coord] = output[src_coord]; } + + [branch] + if (groupIndex == 0) + { + probeOffset = lerp(probeOffset, probeOffsetNew, 0.01); + const float3 limit = ddgi_cellsize() * 0.5; + probeOffset = clamp(probeOffset, -limit, limit); + DDGIProbeOffset ofs; + ofs.store(probeOffset); + ddgiOffsetBuffer.Store(probeIndex * sizeof(DDGIProbeOffset), ofs); + } #else // Copy color borders: for (uint index = groupIndex; index < 36; index += THREADCOUNT * THREADCOUNT) diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h index bf263bcc8..23a8b5ea5 100644 --- a/WickedEngine/wiEmittedParticle.h +++ b/WickedEngine/wiEmittedParticle.h @@ -8,8 +8,6 @@ #include "wiECS.h" #include "wiScene_Decl.h" -#include - namespace wi { class Archive; diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index 985385b5c..46de1b219 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -8,8 +8,6 @@ #include "wiVector.h" #include "wiScene_Decl.h" -#include - namespace wi { class Archive; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index f952ae862..833c24698 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -5681,12 +5681,12 @@ void DrawDebugWorld( } - if (GetDDGIDebugEnabled()) + if (GetDDGIDebugEnabled() && GetDDGIEnabled()) { device->EventBegin("Debug DDGI", cmd); device->BindPipelineState(&PSO_debug[DEBUGRENDERING_DDGI], cmd); - device->DrawInstanced(2880, DDGI_GRID_DIMENSIONS.x* DDGI_GRID_DIMENSIONS.y* DDGI_GRID_DIMENSIONS.z, 0, 0, cmd); // uv-sphere + device->DrawInstanced(2880, DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y * DDGI_GRID_DIMENSIONS.z, 0, 0, cmd); // uv-sphere device->EventEnd(cmd); } @@ -8077,6 +8077,7 @@ void DDGI( GPUBarrier::Buffer(&scene.ddgiRayBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), GPUBarrier::Image(&scene.ddgiColorTexture[1], ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), GPUBarrier::Image(&scene.ddgiDepthTexture[1], ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), + GPUBarrier::Buffer(&scene.ddgiOffsetBuffer, ResourceState::SHADER_RESOURCE_COMPUTE, ResourceState::UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8117,6 +8118,7 @@ void DDGI( const GPUResource* uavs[] = { &scene.ddgiDepthTexture[1], + &scene.ddgiOffsetBuffer, }; device->BindUAVs(uavs, 0, arraysize(uavs), cmd); @@ -8129,6 +8131,7 @@ void DDGI( GPUBarrier barriers[] = { GPUBarrier::Image(&scene.ddgiColorTexture[1], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), GPUBarrier::Image(&scene.ddgiDepthTexture[1], ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), + GPUBarrier::Buffer(&scene.ddgiOffsetBuffer, ResourceState::UNORDERED_ACCESS, ResourceState::SHADER_RESOURCE_COMPUTE), }; device->Barrier(barriers, arraysize(barriers), cmd); } diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index dce175dcf..ca79a2008 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -1790,6 +1790,13 @@ namespace wi::scene device->CreateBuffer(&buf, nullptr, &ddgiRayBuffer); device->SetName(&ddgiRayBuffer, "ddgiRayBuffer"); + buf.stride = sizeof(DDGIProbeOffset); + buf.size = buf.stride * DDGI_PROBE_COUNT; + buf.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE; + buf.misc_flags = ResourceMiscFlag::BUFFER_RAW; + device->CreateBuffer(&buf, nullptr, &ddgiOffsetBuffer); + device->SetName(&ddgiOffsetBuffer, "ddgiOffsetBuffer"); + TextureDesc tex; tex.width = DDGI_COLOR_TEXTURE_WIDTH; tex.height = DDGI_COLOR_TEXTURE_HEIGHT; @@ -1815,6 +1822,8 @@ namespace wi::scene } else if (ddgiColorTexture[0].IsValid()) { + ddgiRayBuffer = {}; + ddgiOffsetBuffer = {}; ddgiColorTexture[0] = {}; ddgiColorTexture[1] = {}; ddgiDepthTexture[0] = {}; @@ -1872,6 +1881,7 @@ namespace wi::scene shaderscene.ddgi.color_texture = device->GetDescriptorIndex(&ddgiColorTexture[0], SubresourceType::SRV); shaderscene.ddgi.depth_texture = device->GetDescriptorIndex(&ddgiDepthTexture[0], SubresourceType::SRV); + shaderscene.ddgi.offset_buffer = device->GetDescriptorIndex(&ddgiOffsetBuffer, SubresourceType::SRV); shaderscene.ddgi.grid_min.x = shaderscene.aabb_min.x - 1; shaderscene.ddgi.grid_min.y = shaderscene.aabb_min.y - 1; shaderscene.ddgi.grid_min.z = shaderscene.aabb_min.z - 1; @@ -1888,6 +1898,9 @@ namespace wi::scene shaderscene.ddgi.cell_size.x = shaderscene.ddgi.grid_extents.x / (DDGI_GRID_DIMENSIONS.x - 1); shaderscene.ddgi.cell_size.y = shaderscene.ddgi.grid_extents.y / (DDGI_GRID_DIMENSIONS.y - 1); shaderscene.ddgi.cell_size.z = shaderscene.ddgi.grid_extents.z / (DDGI_GRID_DIMENSIONS.z - 1); + shaderscene.ddgi.cell_size_rcp.x = 1.0f / shaderscene.ddgi.cell_size.x; + shaderscene.ddgi.cell_size_rcp.y = 1.0f / shaderscene.ddgi.cell_size.y; + shaderscene.ddgi.cell_size_rcp.z = 1.0f / shaderscene.ddgi.cell_size.z; shaderscene.ddgi.max_distance = std::max(shaderscene.ddgi.cell_size.x, std::max(shaderscene.ddgi.cell_size.y, shaderscene.ddgi.cell_size.z)) * 1.5f; } void Scene::Clear() diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index cd3bf983b..9eba85692 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -1338,6 +1338,7 @@ namespace wi::scene // DDGI resources: uint ddgi_frameIndex = 0; wi::graphics::GPUBuffer ddgiRayBuffer; + wi::graphics::GPUBuffer ddgiOffsetBuffer; wi::graphics::Texture ddgiColorTexture[2]; wi::graphics::Texture ddgiDepthTexture[2]; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 5fc5b8f13..e0ac44aca 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 60; // minor bug fixes, alterations, refactors, updates - const int revision = 22; + const int revision = 23; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);