ddgi probe offsets

This commit is contained in:
Turánszki János
2022-01-23 18:48:50 +01:00
parent ff8a317e17
commit 5b02548268
10 changed files with 87 additions and 14 deletions
+29 -2
View File
@@ -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<DDGIProbeOffset>(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)
@@ -43,6 +43,9 @@ struct ShaderScene
float max_distance;
float3 grid_extents_rcp;
int offset_buffer;
float3 cell_size_rcp;
float padding0;
};
DDGI ddgi;
+1 -1
View File
@@ -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)));
+34 -4
View File
@@ -17,6 +17,7 @@ static const float WEIGHT_EPSILON = 0.0001;
#ifdef DDGI_UPDATE_DEPTH
static const uint THREADCOUNT = DDGI_DEPTH_RESOLUTION;
RWTexture2D<float2> output : register(u0);
RWByteAddressBuffer ddgiOffsetBuffer:register(u1);
#else
static const uint THREADCOUNT = DDGI_COLOR_RESOLUTION;
RWTexture2D<float3> 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<DDGIProbeOffset>(probeIndex * sizeof(DDGIProbeOffset), ofs);
}
float3 probeOffset = ddgiOffsetBuffer.Load<DDGIProbeOffset>(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<DDGIProbeOffset>(probeIndex * sizeof(DDGIProbeOffset), ofs);
}
#else
// Copy color borders:
for (uint index = groupIndex; index < 36; index += THREADCOUNT * THREADCOUNT)
-2
View File
@@ -8,8 +8,6 @@
#include "wiECS.h"
#include "wiScene_Decl.h"
#include <memory>
namespace wi
{
class Archive;
-2
View File
@@ -8,8 +8,6 @@
#include "wiVector.h"
#include "wiScene_Decl.h"
#include <memory>
namespace wi
{
class Archive;
+5 -2
View File
@@ -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);
}
+13
View File
@@ -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()
+1
View File
@@ -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];
+1 -1
View File
@@ -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);