Add random per-probe rotation for rays tracing in DDGI
This commit is contained in:
@@ -46,6 +46,7 @@ GPU_CB_STRUCT(Data0 {
|
|||||||
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
|
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
|
||||||
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
|
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
|
||||||
ShaderGBufferData GBuffer;
|
ShaderGBufferData GBuffer;
|
||||||
|
Float4 RaysRotation;
|
||||||
float Padding0;
|
float Padding0;
|
||||||
uint32 ProbesCount;
|
uint32 ProbesCount;
|
||||||
float ResetBlend;
|
float ResetBlend;
|
||||||
@@ -379,7 +380,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
desc2 = GPUBufferDescription::Buffer(sizeof(GPUDispatchIndirectArgs) * Math::DivideAndRoundUp(probesCountCascade, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT), GPUBufferFlags::Argument | GPUBufferFlags::UnorderedAccess, PixelFormat::R32_UInt, nullptr, sizeof(uint32));
|
desc2 = GPUBufferDescription::Buffer(sizeof(GPUDispatchIndirectArgs) * Math::DivideAndRoundUp(probesCountCascade, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT), GPUBufferFlags::Argument | GPUBufferFlags::UnorderedAccess, PixelFormat::R32_UInt, nullptr, sizeof(uint32));
|
||||||
INIT_BUFFER(UpdateProbesInitArgs, "DDGI.UpdateProbesInitArgs");
|
INIT_BUFFER(UpdateProbesInitArgs, "DDGI.UpdateProbesInitArgs");
|
||||||
#undef INIT_BUFFER
|
#undef INIT_BUFFER
|
||||||
LOG(Info, "Dynamic Diffuse Global Illumination memory usage: {0} MB, probes: {1}", memUsage / 1024 / 1024, probesCountTotal);
|
LOG(Info, "Dynamic Diffuse Global Illumination probes: {0}, memory usage: {1} MB", probesCountTotal, memUsage / (1024 * 1024));
|
||||||
clear = true;
|
clear = true;
|
||||||
}
|
}
|
||||||
#if COMPILE_WITH_DEV_ENV
|
#if COMPILE_WITH_DEV_ENV
|
||||||
@@ -465,14 +466,15 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View();
|
ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View();
|
||||||
ddgiData.Result.ProbesIrradiance = ddgiData.ProbesIrradiance->View();
|
ddgiData.Result.ProbesIrradiance = ddgiData.ProbesIrradiance->View();
|
||||||
|
|
||||||
|
Data0 data;
|
||||||
|
|
||||||
// Compute random rotation matrix for probe rays orientation (randomized every frame)
|
// Compute random rotation matrix for probe rays orientation (randomized every frame)
|
||||||
Matrix3x3 raysRotationMatrix;
|
Matrix3x3 raysRotationMatrix;
|
||||||
CalculateVolumeRandomRotation(raysRotationMatrix);
|
CalculateVolumeRandomRotation(raysRotationMatrix);
|
||||||
Quaternion& raysRotation = *(Quaternion*)&ddgiData.Result.Constants.RaysRotation;
|
Quaternion& raysRotation = *(Quaternion*)&data.RaysRotation;
|
||||||
Quaternion::RotationMatrix(raysRotationMatrix, raysRotation);
|
Quaternion::RotationMatrix(raysRotationMatrix, raysRotation);
|
||||||
raysRotation.Conjugate();
|
raysRotation.Conjugate();
|
||||||
|
|
||||||
Data0 data;
|
|
||||||
data.DDGI = ddgiData.Result.Constants;
|
data.DDGI = ddgiData.Result.Constants;
|
||||||
data.GlobalSDF = bindingDataSDF.Constants;
|
data.GlobalSDF = bindingDataSDF.Constants;
|
||||||
data.GlobalSurfaceAtlas = bindingDataSurfaceAtlas.Constants;
|
data.GlobalSurfaceAtlas = bindingDataSurfaceAtlas.Constants;
|
||||||
@@ -638,7 +640,6 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
|||||||
auto& ddgiData = *renderBuffers->GetCustomBuffer<DDGICustomBuffer>(TEXT("DDGI"));
|
auto& ddgiData = *renderBuffers->GetCustomBuffer<DDGICustomBuffer>(TEXT("DDGI"));
|
||||||
if (render && ddgiData.LastFrameUsed == Engine::FrameCount)
|
if (render && ddgiData.LastFrameUsed == Engine::FrameCount)
|
||||||
render = false;
|
render = false;
|
||||||
|
|
||||||
PROFILE_GPU_CPU("Dynamic Diffuse Global Illumination");
|
PROFILE_GPU_CPU("Dynamic Diffuse Global Illumination");
|
||||||
|
|
||||||
if (render)
|
if (render)
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ public:
|
|||||||
float ProbeHistoryWeight;
|
float ProbeHistoryWeight;
|
||||||
float RayMaxDistance;
|
float RayMaxDistance;
|
||||||
float IndirectLightingIntensity;
|
float IndirectLightingIntensity;
|
||||||
Float4 RaysRotation;
|
|
||||||
Float3 ViewPos;
|
Float3 ViewPos;
|
||||||
uint32 RaysCount;
|
uint32 RaysCount;
|
||||||
Float3 FallbackIrradiance;
|
Float3 FallbackIrradiance;
|
||||||
|
|||||||
@@ -742,7 +742,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
return true;
|
return true;
|
||||||
memUsage += surfaceAtlasData.ChunksBuffer->GetMemoryUsage();
|
memUsage += surfaceAtlasData.ChunksBuffer->GetMemoryUsage();
|
||||||
}
|
}
|
||||||
LOG(Info, "Global Surface Atlas resolution: {0}, memory usage: {1} MB", resolution, memUsage / 1024 / 1024);
|
LOG(Info, "Global Surface Atlas resolution: {0}, memory usage: {1} MB", resolution, memUsage / (1024 * 1024));
|
||||||
}
|
}
|
||||||
for (SceneRendering* scene : renderContext.List->Scenes)
|
for (SceneRendering* scene : renderContext.List->Scenes)
|
||||||
surfaceAtlasData.ListenSceneRendering(scene);
|
surfaceAtlasData.ListenSceneRendering(scene);
|
||||||
|
|||||||
@@ -764,7 +764,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint64 memoryUsage = sdfData.Texture->GetMemoryUsage() + sdfData.TextureMip->GetMemoryUsage();
|
uint64 memoryUsage = sdfData.Texture->GetMemoryUsage() + sdfData.TextureMip->GetMemoryUsage();
|
||||||
LOG(Info, "Global SDF memory usage: {0} MB", memoryUsage / 1024 / 1024);
|
LOG(Info, "Global SDF memory usage: {0} MB", memoryUsage / (1024 * 1024));
|
||||||
}
|
}
|
||||||
if (sdfData.Origin != renderContext.View.Origin)
|
if (sdfData.Origin != renderContext.View.Origin)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ struct DDGIData
|
|||||||
float ProbeHistoryWeight;
|
float ProbeHistoryWeight;
|
||||||
float RayMaxDistance;
|
float RayMaxDistance;
|
||||||
float IndirectLightingIntensity;
|
float IndirectLightingIntensity;
|
||||||
float4 RaysRotation;
|
|
||||||
float3 ViewPos;
|
float3 ViewPos;
|
||||||
uint RaysCount;
|
uint RaysCount;
|
||||||
float3 FallbackIrradiance;
|
float3 FallbackIrradiance;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "./Flax/Common.hlsl"
|
#include "./Flax/Common.hlsl"
|
||||||
#include "./Flax/Math.hlsl"
|
#include "./Flax/Math.hlsl"
|
||||||
|
#include "./Flax/Noise.hlsl"
|
||||||
#include "./Flax/Quaternion.hlsl"
|
#include "./Flax/Quaternion.hlsl"
|
||||||
#include "./Flax/GlobalSignDistanceField.hlsl"
|
#include "./Flax/GlobalSignDistanceField.hlsl"
|
||||||
#include "./Flax/GI/GlobalSurfaceAtlas.hlsl"
|
#include "./Flax/GI/GlobalSurfaceAtlas.hlsl"
|
||||||
@@ -30,6 +31,7 @@ DDGIData DDGI;
|
|||||||
GlobalSDFData GlobalSDF;
|
GlobalSDFData GlobalSDF;
|
||||||
GlobalSurfaceAtlasData GlobalSurfaceAtlas;
|
GlobalSurfaceAtlasData GlobalSurfaceAtlas;
|
||||||
GBufferData GBuffer;
|
GBufferData GBuffer;
|
||||||
|
float4 RaysRotation;
|
||||||
float Padding0;
|
float Padding0;
|
||||||
uint ProbesCount;
|
uint ProbesCount;
|
||||||
float ResetBlend;
|
float ResetBlend;
|
||||||
@@ -55,10 +57,19 @@ float3 GetSphericalFibonacci(float sampleIndex, float samplesCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculates a random normalized ray direction (based on the ray index and the current probes rotation phrase)
|
// Calculates a random normalized ray direction (based on the ray index and the current probes rotation phrase)
|
||||||
float3 GetProbeRayDirection(DDGIData data, uint rayIndex)
|
float3 GetProbeRayDirection(DDGIData data, uint rayIndex, uint raysCount, uint probeIndex, uint3 probeCoords)
|
||||||
{
|
{
|
||||||
float3 direction = GetSphericalFibonacci((float)rayIndex, (float)data.RaysCount);
|
float4 rotation = RaysRotation;
|
||||||
return normalize(QuaternionRotate(data.RaysRotation, direction));
|
|
||||||
|
// Randomize rotation per-probe (otherwise all probes are in sync)
|
||||||
|
float3 probePos = (float3)probeCoords / (float3)data.ProbesCounts;
|
||||||
|
float3 randomAxis = normalize(Mod289(probePos));
|
||||||
|
float randomAngle = (float)probeIndex / (float)ProbesCount * (2.0f * PI);
|
||||||
|
rotation = QuaternionMultiply(rotation, QuaternionFromAxisAngle(randomAxis, randomAngle));
|
||||||
|
|
||||||
|
// Random rotation per-ray - relative to the per-frame rays rotation
|
||||||
|
float3 direction = GetSphericalFibonacci((float)rayIndex, (float)raysCount);
|
||||||
|
return normalize(QuaternionRotate(rotation, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates amount of rays to allocate for a probe
|
// Calculates amount of rays to allocate for a probe
|
||||||
@@ -299,7 +310,7 @@ Texture2D<snorm float4> ProbesData : register(t7);
|
|||||||
TextureCube Skybox : register(t8);
|
TextureCube Skybox : register(t8);
|
||||||
ByteAddressBuffer ActiveProbes : register(t9);
|
ByteAddressBuffer ActiveProbes : register(t9);
|
||||||
|
|
||||||
// Compute shader for tracing rays for probes using Global SDF and Global Surface Atlas.
|
// Compute shader for tracing rays for probes using Global SDF and Global Surface Atlas (1 ray per-thread).
|
||||||
META_CS(true, FEATURE_LEVEL_SM5)
|
META_CS(true, FEATURE_LEVEL_SM5)
|
||||||
META_PERMUTATION_1(DDGI_TRACE_RAYS_COUNT=96)
|
META_PERMUTATION_1(DDGI_TRACE_RAYS_COUNT=96)
|
||||||
META_PERMUTATION_1(DDGI_TRACE_RAYS_COUNT=128)
|
META_PERMUTATION_1(DDGI_TRACE_RAYS_COUNT=128)
|
||||||
@@ -320,7 +331,7 @@ void CS_TraceRays(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
if (probeState == DDGI_PROBE_STATE_INACTIVE || rayIndex >= probeRaysCount)
|
if (probeState == DDGI_PROBE_STATE_INACTIVE || rayIndex >= probeRaysCount)
|
||||||
return; // Skip disabled probes or if current thread's ray is unused
|
return; // Skip disabled probes or if current thread's ray is unused
|
||||||
float3 probePosition = DecodeDDGIProbePosition(DDGI, probeData, CascadeIndex, probeIndex, probeCoords);
|
float3 probePosition = DecodeDDGIProbePosition(DDGI, probeData, CascadeIndex, probeIndex, probeCoords);
|
||||||
float3 probeRayDirection = GetProbeRayDirection(DDGI, rayIndex);
|
float3 probeRayDirection = GetProbeRayDirection(DDGI, rayIndex, probeRaysCount, probeIndex, probeCoords);
|
||||||
|
|
||||||
// Trace ray with Global SDF
|
// Trace ray with Global SDF
|
||||||
GlobalSDFTrace trace;
|
GlobalSDFTrace trace;
|
||||||
@@ -428,7 +439,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
|||||||
float rayDistance = ProbesTrace[uint2(rayIndex, GroupId.x)].w;
|
float rayDistance = ProbesTrace[uint2(rayIndex, GroupId.x)].w;
|
||||||
CachedProbesTraceDistance[rayIndex] = min(abs(rayDistance), distanceLimit);
|
CachedProbesTraceDistance[rayIndex] = min(abs(rayDistance), distanceLimit);
|
||||||
#endif
|
#endif
|
||||||
CachedProbesTraceDirection[rayIndex] = GetProbeRayDirection(DDGI, rayIndex);
|
CachedProbesTraceDirection[rayIndex] = GetProbeRayDirection(DDGI, rayIndex, probeRaysCount, probeIndex, probeCoords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GroupMemoryBarrierWithGroupSync();
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
#ifndef __MATH__
|
#ifndef __MATH__
|
||||||
#define __MATH__
|
#define __MATH__
|
||||||
|
|
||||||
|
#define RadiansToDegrees (180.0f / PI)
|
||||||
|
#define DegreesToRadians (PI / 180.0f)
|
||||||
|
|
||||||
uint NextPow2(uint value)
|
uint NextPow2(uint value)
|
||||||
{
|
{
|
||||||
uint mask = (1 << firstbithigh(value)) - 1;
|
uint mask = (1 << firstbithigh(value)) - 1;
|
||||||
|
|||||||
@@ -71,6 +71,24 @@ float2 rand2dTo2d(float2 value)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float rand3dTo1d(float3 value, float3 dotDir = float3(12.9898, 78.233, 37.719))
|
||||||
|
{
|
||||||
|
// https://www.ronja-tutorials.com/post/024-white-noise/
|
||||||
|
float3 smallValue = sin(value);
|
||||||
|
float random = dot(smallValue, dotDir);
|
||||||
|
return frac(sin(random) * 143758.5453);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 rand3dTo3d(float3 value)
|
||||||
|
{
|
||||||
|
// https://www.ronja-tutorials.com/post/024-white-noise/
|
||||||
|
return float3(
|
||||||
|
rand3dTo1d(value, float3(12.989, 78.233, 37.719)),
|
||||||
|
rand3dTo1d(value, float3(39.346, 11.135, 83.155)),
|
||||||
|
rand3dTo1d(value, float3(73.156, 52.235, 09.151))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Classic Perlin noise
|
// Classic Perlin noise
|
||||||
float PerlinNoise(float2 p)
|
float PerlinNoise(float2 p)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -15,4 +15,9 @@ float3 QuaternionRotate(float4 q, float3 v)
|
|||||||
return (v * (q.w * q.w - b2) + b * (dot(v, b) * 2.f) + cross(b, v) * (q.w * 2.f));
|
return (v * (q.w * q.w - b2) + b * (dot(v, b) * 2.f) + cross(b, v) * (q.w * 2.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float4 QuaternionFromAxisAngle(float3 axis, float angle)
|
||||||
|
{
|
||||||
|
return float4(axis * sin(angle * 0.5f), cos(angle * 0.5f));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user