* start ddgi implementation

* update

* updates

* update

* ray data packing

* removed comment

* update

* features.txt

* ddgi disabled by default

* added comments

* comments

* offlineshadercompiler

* updates
This commit is contained in:
Turánszki János
2022-01-19 13:19:14 +01:00
committed by GitHub
parent 90774276df
commit a4580ea2b0
30 changed files with 1312 additions and 38 deletions
+40 -9
View File
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "RendererWindow.h"
#include "Editor.h"
#include "shaders/ShaderInterop_DDGI.h"
void RendererWindow::Create(EditorComponent* editor)
{
@@ -10,7 +11,7 @@ void RendererWindow::Create(EditorComponent* editor)
wi::renderer::SetToDrawGridHelper(true);
wi::renderer::SetToDrawDebugCameras(true);
SetSize(XMFLOAT2(580, 550));
SetSize(XMFLOAT2(580, 600));
float x = 220, y = 5, step = 20, itemheight = 18;
@@ -58,6 +59,16 @@ void RendererWindow::Create(EditorComponent* editor)
});
AddWidget(&resolutionScaleSlider);
GIBoostSlider.Create(1, 10, 1.0f, 1000.0f, "GI Boost: ");
GIBoostSlider.SetTooltip("Adjust the strength of GI.\nNote that values other than 1.0 will cause mismatch with path tracing reference!");
GIBoostSlider.SetSize(XMFLOAT2(100, itemheight));
GIBoostSlider.SetPos(XMFLOAT2(x, y += step));
GIBoostSlider.SetValue(wi::renderer::GetGIBoost());
GIBoostSlider.OnSlide([editor](wi::gui::EventArgs args) {
wi::renderer::SetGIBoost(args.fValue);
});
AddWidget(&GIBoostSlider);
surfelGICheckBox.Create("Surfel GI: ");
surfelGICheckBox.SetTooltip("Surfel GI is a raytraced diffuse GI using raytracing and surface cache.");
surfelGICheckBox.SetPos(XMFLOAT2(x, y += step));
@@ -84,15 +95,35 @@ void RendererWindow::Create(EditorComponent* editor)
});
AddWidget(&surfelGIDebugComboBox);
surfelGIBoostSlider.Create(1, 10, 1.0f, 1000.0f, "Surfel GI Boost: ");
surfelGIBoostSlider.SetTooltip("Adjust the strength of surfel GI.\nNote that values other than 1.0 will cause mismatch with path tracing reference");
surfelGIBoostSlider.SetSize(XMFLOAT2(100, itemheight));
surfelGIBoostSlider.SetPos(XMFLOAT2(x, y += step));
surfelGIBoostSlider.SetValue(wi::renderer::GetSurfelGIBoost());
surfelGIBoostSlider.OnSlide([editor](wi::gui::EventArgs args) {
wi::renderer::SetSurfelGIBoost(args.fValue);
ddgiCheckBox.Create("DDGI: ");
ddgiCheckBox.SetTooltip("Toggle Dynamic Diffuse Global Illumination (DDGI).");
ddgiCheckBox.SetPos(XMFLOAT2(x, y += step));
ddgiCheckBox.SetSize(XMFLOAT2(itemheight, itemheight));
ddgiCheckBox.OnClick([](wi::gui::EventArgs args) {
wi::renderer::SetDDGIEnabled(args.bValue);
});
AddWidget(&surfelGIBoostSlider);
ddgiCheckBox.SetCheck(wi::renderer::GetDDGIEnabled());
AddWidget(&ddgiCheckBox);
ddgiDebugCheckBox.Create("DEBUG: ");
ddgiDebugCheckBox.SetTooltip("Toggle DDGI probe visualization.");
ddgiDebugCheckBox.SetPos(XMFLOAT2(x + 122, y));
ddgiDebugCheckBox.SetSize(XMFLOAT2(itemheight, itemheight));
ddgiDebugCheckBox.OnClick([](wi::gui::EventArgs args) {
wi::renderer::SetDDGIDebugEnabled(args.bValue);
});
ddgiDebugCheckBox.SetCheck(wi::renderer::GetDDGIDebugEnabled());
AddWidget(&ddgiDebugCheckBox);
ddgiRayCountSlider.Create(32, DDGI_MAX_RAYCOUNT, 64, DDGI_MAX_RAYCOUNT - 32, "DDGI RayCount: ");
ddgiRayCountSlider.SetTooltip("Adjust the ray count per DDGI probe.");
ddgiRayCountSlider.SetSize(XMFLOAT2(100, itemheight));
ddgiRayCountSlider.SetPos(XMFLOAT2(x, y += step));
ddgiRayCountSlider.SetValue((float)wi::renderer::GetDDGIRayCount());
ddgiRayCountSlider.OnSlide([&](wi::gui::EventArgs args) {
wi::renderer::SetDDGIRayCount((uint32_t)args.iValue);
});
AddWidget(&ddgiRayCountSlider);
voxelRadianceCheckBox.Create("Voxel GI: ");
voxelRadianceCheckBox.SetTooltip("Toggle voxel Global Illumination computation.");
+4 -1
View File
@@ -27,9 +27,12 @@ public:
wi::gui::ComboBox swapchainComboBox;
wi::gui::CheckBox occlusionCullingCheckBox;
wi::gui::Slider resolutionScaleSlider;
wi::gui::Slider GIBoostSlider;
wi::gui::CheckBox surfelGICheckBox;
wi::gui::ComboBox surfelGIDebugComboBox;
wi::gui::Slider surfelGIBoostSlider;
wi::gui::CheckBox ddgiCheckBox;
wi::gui::CheckBox ddgiDebugCheckBox;
wi::gui::Slider ddgiRayCountSlider;
wi::gui::CheckBox voxelRadianceCheckBox;
wi::gui::CheckBox voxelRadianceDebugCheckBox;
wi::gui::CheckBox voxelRadianceSecondaryBounceCheckBox;
+7
View File
@@ -234,6 +234,10 @@ int main(int argc, char* argv[])
"surfel_binningCS.hlsl",
"surfel_raytraceCS_rtapi.hlsl",
"surfel_raytraceCS.hlsl",
"ddgi_raytraceCS.hlsl",
"ddgi_raytraceCS_rtapi.hlsl",
"ddgi_updateCS.hlsl",
"ddgi_updateCS_depth.hlsl",
};
shaders[static_cast<size_t>(ShaderStage::PS)] = {
@@ -309,6 +313,7 @@ int main(int argc, char* argv[])
"captureImpostorPS_normal.hlsl" ,
"captureImpostorPS_surface.hlsl" ,
"captureImpostorPS_albedo.hlsl" ,
"ddgi_debugPS.hlsl" ,
};
shaders[static_cast<size_t>(ShaderStage::VS)] = {
@@ -357,6 +362,7 @@ int main(int argc, char* argv[])
"cubeShadowVS_transparent.hlsl" ,
"cubeShadowVS_transparent_emulation.hlsl" ,
"occludeeVS.hlsl",
"ddgi_debugVS.hlsl",
};
shaders[static_cast<size_t>(ShaderStage::GS)] = {
@@ -400,6 +406,7 @@ int main(int argc, char* argv[])
minshadermodels["rtshadowCS.hlsl"] = ShaderModel::SM_6_5;
minshadermodels["rtaoCS.hlsl"] = ShaderModel::SM_6_5;
minshadermodels["surfel_raytraceCS_rtapi.hlsl"] = ShaderModel::SM_6_5;
minshadermodels["ddgi_raytraceCS_rtapi.hlsl"] = ShaderModel::SM_6_5;
minshadermodels["rtreflectionCS.hlsl"] = ShaderModel::SM_6_5;
wi::jobsystem::context ctx;
+365
View File
@@ -0,0 +1,365 @@
#ifndef WI_SHADERINTEROP_DDGI_H
#define WI_SHADERINTEROP_DDGI_H
#include "ShaderInterop.h"
#include "ShaderInterop_Renderer.h"
static const uint3 DDGI_GRID_DIMENSIONS = uint3(32, 8, 32); // The scene extents will be subdivided into a grid of this resolution, each grid cell will have one probe
static const uint DDGI_PROBE_COUNT = DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y * DDGI_GRID_DIMENSIONS.z;
static const uint DDGI_MAX_RAYCOUNT = 512; // affects global ray buffer size
static const uint DDGI_COLOR_RESOLUTION = 8; // this should not be modified, border update code is fixed
static const uint DDGI_COLOR_TEXELS = 1 + DDGI_COLOR_RESOLUTION + 1; // with border
static const uint DDGI_DEPTH_RESOLUTION = 16; // this should not be modified, border update code is fixed
static const uint DDGI_DEPTH_TEXELS = 1 + DDGI_DEPTH_RESOLUTION + 1; // with border
static const uint DDGI_COLOR_TEXTURE_WIDTH = DDGI_COLOR_TEXELS * DDGI_GRID_DIMENSIONS.x * DDGI_GRID_DIMENSIONS.y;
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;
#define DDGI_LINEAR_BLENDING
struct DDGIPushConstants
{
uint instanceInclusionMask;
uint frameIndex;
uint rayCount;
};
struct DDGIRayData
{
float3 direction;
float depth;
float4 radiance;
};
struct DDGIRayDataPacked
{
uint4 data;
#ifndef __cplusplus
inline void store(DDGIRayData rayData)
{
data.xy = pack_half4(float4(rayData.direction, rayData.depth));
data.zw = pack_half4(rayData.radiance);
}
inline DDGIRayData load()
{
DDGIRayData rayData;
float4 unpk = unpack_half4(data.xy);
rayData.direction = unpk.xyz;
rayData.depth = unpk.w;
rayData.radiance = unpack_half4(data.zw);
return rayData;
}
#endif // __cplusplus
};
#ifndef __cplusplus
inline float3 ddgi_cellsize()
{
return GetScene().ddgi.cell_size;
}
inline float ddgi_max_distance()
{
return GetScene().ddgi.max_distance;
}
inline uint3 ddgi_base_probe_coord(float3 P)
{
float3 normalized_pos = (P - GetScene().ddgi.grid_min) * GetScene().ddgi.grid_extents_rcp;
return floor(normalized_pos * (DDGI_GRID_DIMENSIONS - 1));
}
inline uint3 ddgi_probe_coord(uint probeIndex)
{
return unflatten3D(probeIndex, DDGI_GRID_DIMENSIONS);
}
inline uint ddgi_probe_index(uint3 probeCoord)
{
return flatten3D(probeCoord, DDGI_GRID_DIMENSIONS);
}
inline float3 ddgi_probe_position(uint3 probeCoord)
{
return GetScene().ddgi.grid_min + probeCoord * ddgi_cellsize();
}
inline uint2 ddgi_probe_color_pixel(uint3 probeCoord)
{
return probeCoord.xz * DDGI_COLOR_TEXELS + uint2(probeCoord.y * DDGI_GRID_DIMENSIONS.x * DDGI_COLOR_TEXELS, 0) + 1;
}
inline float2 ddgi_probe_color_uv(uint3 probeCoord, float3 direction)
{
float2 pixel = ddgi_probe_color_pixel(probeCoord);
pixel += (encode_oct(normalize(direction)) * 0.5 + 0.5) * DDGI_COLOR_RESOLUTION;
return pixel / float2(DDGI_COLOR_TEXTURE_WIDTH, DDGI_COLOR_TEXTURE_HEIGHT);
}
inline uint2 ddgi_probe_depth_pixel(uint3 probeCoord)
{
return probeCoord.xz * DDGI_DEPTH_TEXELS + uint2(probeCoord.y * DDGI_GRID_DIMENSIONS.x * DDGI_DEPTH_TEXELS, 0) + 1;
}
inline float2 ddgi_probe_depth_uv(uint3 probeCoord, float3 direction)
{
float2 pixel = ddgi_probe_depth_pixel(probeCoord);
pixel += (encode_oct(normalize(direction)) * 0.5 + 0.5) * DDGI_DEPTH_RESOLUTION;
return pixel / float2(DDGI_DEPTH_TEXTURE_WIDTH, DDGI_DEPTH_TEXTURE_HEIGHT);
}
// Based on: https://github.com/diharaw/hybrid-rendering/blob/master/src/shaders/gi/gi_common.glsl
float3 ddgi_sample_irradiance(float3 P, float3 N)
{
uint3 base_grid_coord = ddgi_base_probe_coord(P);
float3 base_probe_pos = ddgi_probe_position(base_grid_coord);
float3 sum_irradiance = 0;
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);
// Iterate over adjacent probe cage
for (uint i = 0; i < 8; ++i)
{
// Compute the offset grid coord and clamp to the probe grid boundary
// Offset = 0 or 1 along each axis
uint3 offset = uint3(i, i >> 1, i >> 2) & 1;
uint3 probe_grid_coord = clamp(base_grid_coord + offset, 0, DDGI_GRID_DIMENSIONS - 1);
//int p = ddgi_probe_index(probe_grid_coord);
// Make cosine falloff in tangent plane with respect to the angle from the surface to the probe so that we never
// test a probe that is *behind* the surface.
// It doesn't have to be cosine, but that is efficient to compute and we must clip to the tangent plane.
float3 probe_pos = ddgi_probe_position(probe_grid_coord);
// Bias the position at which visibility is computed; this
// avoids performing a shadow test *at* a surface, which is a
// dangerous location because that is exactly the line between
// shadowed and unshadowed. If the normal bias is too small,
// there will be light and dark leaks. If it is too large,
// then samples can pass through thin occluders to the other
// side (this can only happen if there are MULTIPLE occluders
// near each other, a wall surface won't pass through itself.)
float3 probe_to_point = P - probe_pos + N * 0.001;
float3 dir = normalize(-probe_to_point);
// Compute the trilinear weights based on the grid cell vertex to smoothly
// transition between probes. Avoid ever going entirely to zero because that
// will cause problems at the border probes. This isn't really a lerp.
// We're using 1-a when offset = 0 and a when offset = 1.
float3 trilinear = lerp(1.0 - alpha, alpha, offset);
float weight = 1.0;
// Clamp all of the multiplies. We can't let the weight go to zero because then it would be
// possible for *all* weights to be equally low and get normalized
// up to 1/n. We want to distinguish between weights that are
// low because of different factors.
#if 0
// Smooth backface test
{
// Computed without the biasing applied to the "dir" variable.
// This test can cause reflection-map looking errors in the image
// (stuff looks shiny) if the transition is poor.
float3 true_direction_to_probe = normalize(probe_pos - P);
// The naive soft backface weight would ignore a probe when
// it is behind the surface. That's good for walls. But for small details inside of a
// room, the normals on the details might rule out all of the probes that have mutual
// visibility to the point. So, we instead use a "wrap shading" test below inspired by
// NPR work.
// weight *= max(0.0001, dot(trueDirectionToProbe, wsN));
// The small offset at the end reduces the "going to zero" impact
// where this is really close to exactly opposite
weight *= sqr(max(0.0001, (dot(true_direction_to_probe, N) + 1.0) * 0.5)) + 0.2;
}
#else
weight *= saturate(dot(dir, N));
#endif
// Moment visibility test
#if 1
[branch]
if(GetScene().ddgi.depth_texture >= 0)
{
//float2 tex_coord = texture_coord_from_direction(-dir, p, ddgi.depth_texture_width, ddgi.depth_texture_height, ddgi.depth_probe_side_length);
float2 tex_coord = ddgi_probe_depth_uv(probe_grid_coord, -dir);
float dist_to_probe = length(probe_to_point);
//float2 temp = textureLod(depth_texture, tex_coord, 0.0f).rg;
float2 temp = bindless_textures[GetScene().ddgi.depth_texture].SampleLevel(sampler_linear_clamp, tex_coord, 0).xy;
float mean = temp.x;
float variance = abs(sqr(temp.x) - temp.y);
// http://www.punkuser.net/vsm/vsm_paper.pdf; equation 5
// Need the max in the denominator because biasing can cause a negative displacement
float chebyshev_weight = variance / (variance + sqr(max(dist_to_probe - mean, 0.0)));
// Increase contrast in the weight
chebyshev_weight = max(pow(chebyshev_weight, 3), 0.0);
weight *= (dist_to_probe <= mean) ? 1.0 : chebyshev_weight;
}
#endif
// Avoid zero weight
weight = max(0.000001, weight);
float3 irradiance_dir = N;
//float2 tex_coord = texture_coord_from_direction(normalize(irradiance_dir), p, ddgi.irradiance_texture_width, ddgi.irradiance_texture_height, ddgi.irradiance_probe_side_length);
float2 tex_coord = ddgi_probe_color_uv(probe_grid_coord, irradiance_dir);
//float3 probe_irradiance = textureLod(irradiance_texture, tex_coord, 0.0f).rgb;
float3 probe_irradiance = bindless_textures[GetScene().ddgi.color_texture].SampleLevel(sampler_linear_clamp, tex_coord, 0).rgb;
// A tiny bit of light is really visible due to log perception, so
// crush tiny weights but keep the curve continuous. This must be done
// before the trilinear weights, because those should be preserved.
const float crush_threshold = 0.2f;
if (weight < crush_threshold)
weight *= weight * weight * (1.0f / sqr(crush_threshold));
// Trilinear weights
weight *= trilinear.x * trilinear.y * trilinear.z;
// Weight in a more-perceptual brightness space instead of radiance space.
// This softens the transitions between probes with respect to translation.
// It makes little difference most of the time, but when there are radical transitions
// between probes this helps soften the ramp.
#ifndef DDGI_LINEAR_BLENDING
probe_irradiance = sqrt(probe_irradiance);
#endif
sum_irradiance += weight * probe_irradiance;
sum_weight += weight;
}
if (sum_weight > 0)
{
float3 net_irradiance = sum_irradiance / sum_weight;
// Go back to linear irradiance
#ifndef DDGI_LINEAR_BLENDING
net_irradiance = sqr(net_irradiance);
#endif
//net_irradiance *= 0.85; // energy preservation
return net_irradiance;
//return 0.5f * PI * net_irradiance;
}
return 0;
}
// Border offsets from: https://github.com/diharaw/hybrid-rendering/blob/master/src/shaders/gi/gi_border_update.glsl
static const uint4 DDGI_COLOR_BORDER_OFFSETS[36] = {
uint4(8, 1, 1, 0),
uint4(7, 1, 2, 0),
uint4(6, 1, 3, 0),
uint4(5, 1, 4, 0),
uint4(4, 1, 5, 0),
uint4(3, 1, 6, 0),
uint4(2, 1, 7, 0),
uint4(1, 1, 8, 0),
uint4(8, 8, 1, 9),
uint4(7, 8, 2, 9),
uint4(6, 8, 3, 9),
uint4(5, 8, 4, 9),
uint4(4, 8, 5, 9),
uint4(3, 8, 6, 9),
uint4(2, 8, 7, 9),
uint4(1, 8, 8, 9),
uint4(1, 8, 0, 1),
uint4(1, 7, 0, 2),
uint4(1, 6, 0, 3),
uint4(1, 5, 0, 4),
uint4(1, 4, 0, 5),
uint4(1, 3, 0, 6),
uint4(1, 2, 0, 7),
uint4(1, 1, 0, 8),
uint4(8, 8, 9, 1),
uint4(8, 7, 9, 2),
uint4(8, 6, 9, 3),
uint4(8, 5, 9, 4),
uint4(8, 4, 9, 5),
uint4(8, 3, 9, 6),
uint4(8, 2, 9, 7),
uint4(8, 1, 9, 8),
uint4(8, 8, 0, 0),
uint4(1, 8, 9, 0),
uint4(8, 1, 0, 9),
uint4(1, 1, 9, 9)
};
static const uint4 DDGI_DEPTH_BORDER_OFFSETS[68] = {
uint4(16, 1, 1, 0),
uint4(15, 1, 2, 0),
uint4(14, 1, 3, 0),
uint4(13, 1, 4, 0),
uint4(12, 1, 5, 0),
uint4(11, 1, 6, 0),
uint4(10, 1, 7, 0),
uint4(9, 1, 8, 0),
uint4(8, 1, 9, 0),
uint4(7, 1, 10, 0),
uint4(6, 1, 11, 0),
uint4(5, 1, 12, 0),
uint4(4, 1, 13, 0),
uint4(3, 1, 14, 0),
uint4(2, 1, 15, 0),
uint4(1, 1, 16, 0),
uint4(16, 16, 1, 17),
uint4(15, 16, 2, 17),
uint4(14, 16, 3, 17),
uint4(13, 16, 4, 17),
uint4(12, 16, 5, 17),
uint4(11, 16, 6, 17),
uint4(10, 16, 7, 17),
uint4(9, 16, 8, 17),
uint4(8, 16, 9, 17),
uint4(7, 16, 10, 17),
uint4(6, 16, 11, 17),
uint4(5, 16, 12, 17),
uint4(4, 16, 13, 17),
uint4(3, 16, 14, 17),
uint4(2, 16, 15, 17),
uint4(1, 16, 16, 17),
uint4(1, 16, 0, 1),
uint4(1, 15, 0, 2),
uint4(1, 14, 0, 3),
uint4(1, 13, 0, 4),
uint4(1, 12, 0, 5),
uint4(1, 11, 0, 6),
uint4(1, 10, 0, 7),
uint4(1, 9, 0, 8),
uint4(1, 8, 0, 9),
uint4(1, 7, 0, 10),
uint4(1, 6, 0, 11),
uint4(1, 5, 0, 12),
uint4(1, 4, 0, 13),
uint4(1, 3, 0, 14),
uint4(1, 2, 0, 15),
uint4(1, 1, 0, 16),
uint4(16, 16, 17, 1),
uint4(16, 15, 17, 2),
uint4(16, 14, 17, 3),
uint4(16, 13, 17, 4),
uint4(16, 12, 17, 5),
uint4(16, 11, 17, 6),
uint4(16, 10, 17, 7),
uint4(16, 9, 17, 8),
uint4(16, 8, 17, 9),
uint4(16, 7, 17, 10),
uint4(16, 6, 17, 11),
uint4(16, 5, 17, 12),
uint4(16, 4, 17, 13),
uint4(16, 3, 17, 14),
uint4(16, 2, 17, 15),
uint4(16, 1, 17, 16),
uint4(16, 16, 0, 0),
uint4(1, 16, 17, 0),
uint4(16, 1, 0, 17),
uint4(1, 1, 17, 17)
};
#endif // __cplusplus
#endif // WI_SHADERINTEROP_DDGI_H
+17 -1
View File
@@ -30,6 +30,22 @@ struct ShaderScene
float padding6;
ShaderWeather weather;
struct DDGI
{
float3 grid_min;
int color_texture;
float3 grid_extents;
int depth_texture;
float3 cell_size;
float max_distance;
float3 grid_extents_rcp;
float padding0;
};
DDGI ddgi;
};
static const uint SHADERMATERIAL_OPTION_BIT_USE_VERTEXCOLORS = 1 << 0;
@@ -590,7 +606,7 @@ struct FrameCB
int texture_voxelgi_index;
int buffer_entityarray_index;
int buffer_entitymatrixarray_index;
float surfelgi_boost;
float gi_boost;
ShaderScene scene;
};
@@ -481,6 +481,28 @@
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Vertex</ShaderType>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_debugPS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Pixel</ShaderType>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_debugVS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_raytraceCS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_raytraceCS_rtapi.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_updateCS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_updateCS_depth.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Compute</ShaderType>
<ShaderModel Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">4.0</ShaderModel>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)occludeeVS.hlsl">
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Vertex</ShaderType>
<ShaderType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Vertex</ShaderType>
@@ -2809,6 +2831,7 @@
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_BVH.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_DDGI.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_EmittedParticle.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_FFTGenerator.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_Font.h" />
@@ -1004,6 +1004,24 @@
<FxCompile Include="$(MSBuildThisFileDirectory)rtreflectionCS.hlsl">
<Filter>CS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_debugVS.hlsl">
<Filter>VS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_debugPS.hlsl">
<Filter>PS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_raytraceCS.hlsl">
<Filter>CS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_raytraceCS_rtapi.hlsl">
<Filter>CS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_updateCS.hlsl">
<Filter>CS</Filter>
</FxCompile>
<FxCompile Include="$(MSBuildThisFileDirectory)ddgi_updateCS_depth.hlsl">
<Filter>CS</Filter>
</FxCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop.h">
@@ -1048,5 +1066,8 @@
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_Weather.h">
<Filter>interop</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)ShaderInterop_DDGI.h">
<Filter>interop</Filter>
</ClInclude>
</ItemGroup>
</Project>
+15 -6
View File
@@ -124,6 +124,13 @@ struct ClearcoatSurface
float3 F;
};
enum
{
SURFACE_FLAG_BACKFACE = 1u << 0u,
SURFACE_FLAG_RECEIVE_SHADOW = 1u << 1u,
SURFACE_FLAG_GI_APPLIED = 1u << 2u,
};
struct Surface
{
// Fill these yourself:
@@ -147,9 +154,8 @@ struct Surface
float4 sss; // subsurface scattering color * amount
float4 sss_inv; // 1 / (1 + sss)
uint layerMask; // the engine-side layer mask
bool receiveshadow;
float3 facenormal; // surface normal without normal map
bool is_frontface;
uint flags;
// These will be computed when calling Update():
float roughnessBRDF; // roughness input for BRDF functions
@@ -183,8 +189,8 @@ struct Surface
sss = 0;
sss_inv = 1;
layerMask = ~0;
receiveshadow = true;
facenormal = 0;
flags = 0;
sheen.color = 0;
sheen.roughness = 0;
@@ -241,7 +247,10 @@ struct Surface
f0 *= lerp(lerp(float3(0, 0, 0), float3(1, 1, 1), reflectance), baseColor.rgb, metalness);
}
receiveshadow = material.IsReceiveShadow();
if (material.IsReceiveShadow())
{
flags |= SURFACE_FLAG_RECEIVE_SHADOW;
}
}
inline void update()
@@ -279,7 +288,7 @@ struct Surface
#endif // BRDF_CARTOON
}
inline bool IsReceiveShadow() { return receiveshadow; }
inline bool IsReceiveShadow() { return flags & SURFACE_FLAG_RECEIVE_SHADOW; }
ShaderMeshInstance inst;
@@ -440,7 +449,7 @@ struct Surface
N = mad(n0, w, mad(n1, u, n2 * v)); // n0 * w + n1 * u + n2 * v
N = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), N);
N = normalize(N);
if (is_frontface == false && !is_hairparticle && !is_emittedparticle)
if ((flags & SURFACE_FLAG_BACKFACE) && !is_hairparticle && !is_emittedparticle)
{
N = -N;
}
+19
View File
@@ -0,0 +1,19 @@
#include "globals.hlsli"
#include "ShaderInterop_DDGI.h"
struct VSOut
{
float4 pos : SV_Position;
float3 normal : NORMAL;
uint probeIndex : PROBEINDEX;
};
float4 main(VSOut input) : SV_Target
{
Texture2D ddgiColorTexture = bindless_textures[GetScene().ddgi.color_texture];
uint3 probeCoord = ddgi_probe_coord(input.probeIndex);
float3 color = ddgiColorTexture.SampleLevel(sampler_linear_clamp, ddgi_probe_color_uv(probeCoord, input.normal), 0).rgb;
return float4(color, 1);
}
+26
View File
@@ -0,0 +1,26 @@
#include "globals.hlsli"
#include "uvsphere.hlsli"
#include "ShaderInterop_DDGI.h"
struct VSOut
{
float4 pos : SV_Position;
float3 normal : NORMAL;
uint probeIndex : PROBEINDEX;
};
VSOut main(uint vertexID : SV_VertexID, uint instanceID : SV_InstanceID)
{
VSOut o;
o.pos = UVSPHERE[vertexID];
o.normal = o.pos.xyz;
o.pos.xyz *= ddgi_max_distance() * 0.05;
o.probeIndex = instanceID;
const float3 probeCoord = ddgi_probe_coord(o.probeIndex);
const float3 probePosition = ddgi_probe_position(probeCoord);
o.pos.xyz += probePosition;
o.pos = mul(GetCamera().view_projection, o.pos);
return o;
}
+283
View File
@@ -0,0 +1,283 @@
#include "globals.hlsli"
#include "raytracingHF.hlsli"
#include "lightingHF.hlsli"
#include "ShaderInterop_DDGI.h"
// This shader runs one probe per thread group and each thread will trace rays and write the trace result to a ray data buffer
// ray data buffer will be later integrated by ddgi_updateCS shader which updates the DDGI irradiance and depth textures
PUSHCONSTANT(push, DDGIPushConstants);
RWStructuredBuffer<DDGIRayDataPacked> rayBuffer : register(u0);
static const uint THREADCOUNT = 32;
// spherical fibonacci: https://github.com/diharaw/hybrid-rendering/blob/master/src/shaders/gi/gi_ray_trace.rgen
#define madfrac(A, B) ((A) * (B)-floor((A) * (B)))
static const float PHI = sqrt(5) * 0.5 + 0.5;
float3 spherical_fibonacci(float i, float n)
{
float phi = 2.0 * PI * madfrac(i, PHI - 1);
float cos_theta = 1.0 - (2.0 * i + 1.0) * (1.0 / n);
float sin_theta = sqrt(clamp(1.0 - cos_theta * cos_theta, 0.0f, 1.0f));
return float3(cos(phi) * sin_theta, sin(phi) * sin_theta, cos_theta);
}
[numthreads(THREADCOUNT, 1, 1)]
void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex)
{
const uint probeIndex = Gid.x;
const uint3 probeCoord = ddgi_probe_coord(probeIndex);
const float3 probePos = ddgi_probe_position(probeCoord);
float seed = 0.123456;
float2 uv = float2(frac(GetFrame().frame_count.x / 4096.0), DTid.x);
const float3x3 random_orientation = (float3x3)g_xTransform;
for (uint rayIndex = groupIndex; rayIndex < push.rayCount; rayIndex += THREADCOUNT)
{
RayDesc ray;
ray.Origin = probePos;
ray.TMin = 0.0001;
ray.TMax = FLT_MAX;
ray.Direction = normalize(mul(random_orientation, spherical_fibonacci(rayIndex, push.rayCount)));
#ifdef RTAPI
RayQuery<
RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES |
RAY_FLAG_FORCE_OPAQUE
> q;
q.TraceRayInline(
scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure
0, // uint RayFlags
push.instanceInclusionMask, // uint InstanceInclusionMask
ray // RayDesc Ray
);
q.Proceed();
if (q.CommittedStatus() != COMMITTED_TRIANGLE_HIT)
#else
RayHit hit = TraceRay_Closest(ray, push.instanceInclusionMask, seed, uv);
if (hit.distance >= FLT_MAX - 1)
#endif // RTAPI
{
float3 envColor;
[branch]
if (IsStaticSky())
{
// We have envmap information in a texture:
envColor = DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, ray.Direction, 0).rgb);
}
else
{
envColor = GetDynamicSkyColor(ray.Direction, true, true, false, true);
}
DDGIRayData rayData;
rayData.direction = ray.Direction;
rayData.depth = -1;
rayData.radiance = float4(envColor, 1);
rayBuffer[probeIndex * DDGI_MAX_RAYCOUNT + rayIndex].store(rayData);
}
else
{
Surface surface;
float hit_depth = 0;
float3 hit_result = 0;
#ifdef RTAPI
// ray origin updated for next bounce:
ray.Origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT();
hit_depth = q.CommittedRayT();
PrimitiveID prim;
prim.primitiveIndex = q.CommittedPrimitiveIndex();
prim.instanceIndex = q.CommittedInstanceID();
prim.subsetIndex = q.CommittedGeometryIndex();
if (!q.CommittedTriangleFrontFace())
{
surface.flags |= SURFACE_FLAG_BACKFACE;
}
if (!surface.load(prim, q.CommittedTriangleBarycentrics()))
break;
#else
// ray origin updated for next bounce:
ray.Origin = ray.Origin + ray.Direction * hit.distance;
hit_depth = hit.distance;
if (!surface.load(hit.primitiveID, hit.bary))
break;
#endif // RTAPI
surface.P = ray.Origin;
surface.V = -ray.Direction;
surface.update();
#if 1
// Light sampling:
[loop]
for (uint iterator = 0; iterator < GetFrame().lightarray_count; iterator++)
{
ShaderEntity light = load_entity(GetFrame().lightarray_offset + iterator);
Lighting lighting;
lighting.create(0, 0, 0, 0);
float3 L = 0;
float dist = 0;
float NdotL = 0;
switch (light.GetType())
{
case ENTITY_TYPE_DIRECTIONALLIGHT:
{
dist = FLT_MAX;
L = light.GetDirection().xyz;
NdotL = saturate(dot(L, surface.N));
[branch]
if (NdotL > 0)
{
float3 lightColor = light.GetColor().rgb * light.GetEnergy();
[branch]
if (GetFrame().options & OPTION_BIT_REALISTIC_SKY)
{
lightColor *= GetAtmosphericLightTransmittance(GetWeather().atmosphere, surface.P, L, texture_transmittancelut);
}
lighting.direct.diffuse = lightColor;
}
}
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)
{
dist = sqrt(dist2);
L /= dist;
NdotL = saturate(dot(L, surface.N));
[branch]
if (NdotL > 0)
{
const float3 lightColor = light.GetColor().rgb * light.GetEnergy();
lighting.direct.diffuse = lightColor;
const float range2 = light.GetRange() * light.GetRange();
const float att = saturate(1.0 - (dist2 / range2));
const float attenuation = att * att;
lighting.direct.diffuse *= attenuation;
}
}
}
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)
{
dist = sqrt(dist2);
L /= dist;
NdotL = saturate(dot(L, surface.N));
[branch]
if (NdotL > 0)
{
const float SpotFactor = dot(L, light.GetDirection());
const float spotCutOff = light.GetConeAngleCos();
[branch]
if (SpotFactor > spotCutOff)
{
const float3 lightColor = light.GetColor().rgb * light.GetEnergy();
lighting.direct.diffuse = lightColor;
const float range2 = light.GetRange() * light.GetRange();
const float att = saturate(1.0 - (dist2 / range2));
float attenuation = att * att;
attenuation *= saturate((1.0 - (1.0 - SpotFactor) * 1.0 / (1.0 - spotCutOff)));
lighting.direct.diffuse *= attenuation;
}
}
}
}
break;
}
if (NdotL > 0 && dist > 0)
{
float3 shadow = NdotL;
RayDesc newRay;
newRay.Origin = surface.P;
#if 1
newRay.Direction = normalize(lerp(L, sample_hemisphere_cos(L, seed, uv), 0.025f));
#else
newRay.Direction = L;
#endif
newRay.TMin = 0.001;
newRay.TMax = dist;
#ifdef RTAPI
q.TraceRayInline(
scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure
RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, // uint RayFlags
0xFF, // uint InstanceInclusionMask
newRay // RayDesc Ray
);
q.Proceed();
shadow = q.CommittedStatus() == COMMITTED_TRIANGLE_HIT ? 0 : shadow;
#else
shadow = TraceRay_Any(newRay, push.instanceInclusionMask, seed, uv) ? 0 : shadow;
#endif // RTAPI
if (any(shadow))
{
hit_result += max(0, shadow * lighting.direct.diffuse / PI);
}
}
}
#endif
// Infinite bounces based on previous frame probe sampling:
if (push.frameIndex > 0)
{
hit_result += ddgi_sample_irradiance(surface.P, surface.facenormal);
}
hit_result *= surface.albedo;
hit_result += max(0, surface.emissiveColor);
DDGIRayData rayData;
rayData.direction = ray.Direction;
rayData.depth = hit_depth;
rayData.radiance = float4(hit_result, 1);
rayBuffer[probeIndex * DDGI_MAX_RAYCOUNT + rayIndex].store(rayData);
}
}
}
@@ -0,0 +1,2 @@
#define RTAPI
#include "ddgi_raytraceCS.hlsl"
+141
View File
@@ -0,0 +1,141 @@
#include "globals.hlsli"
#include "ShaderInterop_DDGI.h"
// This shader collects all traced rays (one probe per thread group) and integrates them
// Rays are first gathered to shared memory
// Then for each pixel, all traced rays will be evaluated and contributed, weighted based on pixel's own direction and ray's direction
// This shader will run twice in DDGI, once it integrates the radiances
// After that it will also integrate the ray depths, when DDGI_UPDATE_DEPTH is defined
// Based on: https://github.com/diharaw/hybrid-rendering/blob/master/src/shaders/gi/gi_probe_update.glsl
PUSHCONSTANT(push, DDGIPushConstants);
StructuredBuffer<DDGIRayDataPacked> ddgiRayBuffer : register(t0);
static const uint CACHE_SIZE = 64;
groupshared DDGIRayDataPacked ray_cache[CACHE_SIZE];
static const float WEIGHT_EPSILON = 0.0001;
#ifdef DDGI_UPDATE_DEPTH
static const uint THREADCOUNT = DDGI_DEPTH_RESOLUTION;
RWTexture2D<float2> output : register(u0);
#else
static const uint THREADCOUNT = DDGI_COLOR_RESOLUTION;
RWTexture2D<float3> output : register(u0);
#endif // DDGI_UPDATE_DEPTH
[numthreads(THREADCOUNT, THREADCOUNT, 1)]
void main(uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex)
{
const uint probeIndex = Gid.x;
const uint3 probeCoord = ddgi_probe_coord(probeIndex);
const float maxDistance = ddgi_max_distance();
#ifdef DDGI_UPDATE_DEPTH
float2 result = 0;
const uint2 pixel_topleft = ddgi_probe_depth_pixel(probeCoord);
#else
float3 result = 0;
const uint2 pixel_topleft = ddgi_probe_color_pixel(probeCoord);
#endif // DDGI_UPDATE_DEPTH
const uint2 pixel_current = pixel_topleft + GTid.xy;
const uint2 copy_coord = pixel_topleft - 1;
const float3 texel_direction = decode_oct(((GTid.xy + 0.5) / (float2)THREADCOUNT) * 2 - 1);
float total_weight = 0;
uint remaining_rays = push.rayCount;
uint offset = 0;
while (remaining_rays > 0)
{
uint num_rays = min(CACHE_SIZE, remaining_rays);
if (groupIndex < num_rays)
{
ray_cache[groupIndex] = ddgiRayBuffer[probeIndex * DDGI_MAX_RAYCOUNT + groupIndex + offset];
}
GroupMemoryBarrierWithGroupSync();
for (uint r = 0; r < num_rays; ++r)
{
DDGIRayData ray = ray_cache[r].load();
#ifdef DDGI_UPDATE_DEPTH
float ray_probe_distance;
if (ray.depth > 0)
{
ray_probe_distance = clamp(ray.depth - 0.01, 0, maxDistance);
}
else
{
ray_probe_distance = maxDistance;
}
#else
const float3 radiance = ray.radiance.rgb;
#endif // DDGI_UPDATE_DEPTH
float weight = saturate(dot(texel_direction, ray.direction));
#ifdef DDGI_UPDATE_DEPTH
weight = pow(weight, 64);
#endif // DDGI_UPDATE_DEPTH
if (weight > WEIGHT_EPSILON)
{
#ifdef DDGI_UPDATE_DEPTH
result += float2(ray_probe_distance * weight, sqr(ray_probe_distance) * weight);
#else
result += ray.radiance.rgb * weight;
#endif // DDGI_UPDATE_DEPTH
total_weight += weight;
}
}
GroupMemoryBarrierWithGroupSync();
remaining_rays -= num_rays;
offset += num_rays;
}
if (total_weight > WEIGHT_EPSILON)
{
result /= total_weight;
}
#ifdef DDGI_UPDATE_DEPTH
const float2 prev_result = bindless_textures[GetScene().ddgi.depth_texture][pixel_current].xy;
#else
const float3 prev_result = bindless_textures[GetScene().ddgi.color_texture][pixel_current].rgb;
#endif // DDGI_UPDATE_DEPTH
if (push.frameIndex > 0)
{
result = lerp(prev_result, result, 0.02);
}
output[pixel_current] = result;
DeviceMemoryBarrierWithGroupSync();
#ifdef DDGI_UPDATE_DEPTH
// Copy depth borders:
for (uint index = groupIndex; index < 68; index += THREADCOUNT * THREADCOUNT)
{
uint2 src_coord = copy_coord + DDGI_DEPTH_BORDER_OFFSETS[index].xy;
uint2 dst_coord = copy_coord + DDGI_DEPTH_BORDER_OFFSETS[index].zw;
output[dst_coord] = output[src_coord];
}
#else
// Copy color borders:
for (uint index = groupIndex; index < 36; index += THREADCOUNT * THREADCOUNT)
{
uint2 src_coord = copy_coord + DDGI_COLOR_BORDER_OFFSETS[index].xy;
uint2 dst_coord = copy_coord + DDGI_COLOR_BORDER_OFFSETS[index].zw;
output[dst_coord] = output[src_coord];
}
#endif // DDGI_UPDATE_DEPTH
}
@@ -0,0 +1,2 @@
#define DDGI_UPDATE_DEPTH
#include "ddgi_updateCS.hlsl"
+22 -5
View File
@@ -21,6 +21,7 @@
#include "brdf.hlsli"
#include "lightingHF.hlsli"
#include "ShaderInterop_SurfelGI.h"
#include "ShaderInterop_DDGI.h"
// DEFINITIONS
//////////////////
@@ -350,7 +351,7 @@ inline void ApplyEmissive(in Surface surface, inout Lighting lighting)
lighting.direct.specular += surface.emissiveColor;
}
inline void LightMapping(in int lightmap, in float2 ATLAS, inout Lighting lighting)
inline void LightMapping(in int lightmap, in float2 ATLAS, inout Lighting lighting, inout Surface surface)
{
[branch]
if (lightmap >= 0 && any(ATLAS))
@@ -361,6 +362,8 @@ inline void LightMapping(in int lightmap, in float2 ATLAS, inout Lighting lighti
#else
lighting.indirect.diffuse = texture_lightmap.SampleLevel(sampler_linear_clamp, ATLAS, 0).rgb;
#endif // LIGHTMAP_QUALITY_BICUBIC
surface.flags |= SURFACE_FLAG_GI_APPLIED;
}
}
@@ -626,6 +629,13 @@ inline void ForwardLighting(inout Surface surface, inout Lighting lighting)
}
}
[branch]
if ((surface.flags & SURFACE_FLAG_GI_APPLIED) == 0 && GetScene().ddgi.color_texture >= 0)
{
lighting.indirect.diffuse = ddgi_sample_irradiance(surface.P, surface.N);
surface.flags |= SURFACE_FLAG_GI_APPLIED;
}
}
inline void TiledLighting(inout Surface surface, inout Lighting lighting)
@@ -900,15 +910,22 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting)
}
}
#ifndef TRANSPARENT
[branch]
if (GetFrame().options & OPTION_BIT_SURFELGI_ENABLED && GetCamera().texture_surfelgi_index >= 0 && surfel_cellvalid(surfel_cell(surface.P)))
if ((surface.flags & SURFACE_FLAG_GI_APPLIED) == 0 && GetFrame().options & OPTION_BIT_SURFELGI_ENABLED && GetCamera().texture_surfelgi_index >= 0 && surfel_cellvalid(surfel_cell(surface.P)))
{
lighting.indirect.diffuse = bindless_textures[GetCamera().texture_surfelgi_index][surface.pixel].rgb * GetFrame().surfelgi_boost;
lighting.indirect.diffuse = bindless_textures[GetCamera().texture_surfelgi_index][surface.pixel].rgb * GetFrame().gi_boost;
surface.flags |= SURFACE_FLAG_GI_APPLIED;
}
#endif // TRANSPARENT
[branch]
if ((surface.flags & SURFACE_FLAG_GI_APPLIED) == 0 && GetScene().ddgi.color_texture >= 0)
{
lighting.indirect.diffuse = ddgi_sample_irradiance(surface.P, surface.N) * GetFrame().gi_boost;
surface.flags |= SURFACE_FLAG_GI_APPLIED;
}
}
inline void ApplyLighting(in Surface surface, in Lighting lighting, inout float4 color)
@@ -1652,7 +1669,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_Target
#ifdef OBJECTSHADER_USE_ATLAS
LightMapping(load_instance(input.instanceID).lightmap, input.atl, lighting);
LightMapping(load_instance(input.instanceID).lightmap, input.atl, lighting, surface);
#endif // OBJECTSHADER_USE_ATLAS
+5 -1
View File
@@ -114,7 +114,11 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
prim.instanceIndex = q.CommittedInstanceID();
prim.subsetIndex = q.CommittedGeometryIndex();
surface.is_frontface = q.CommittedTriangleFrontFace();
if (!q.CommittedTriangleFrontFace())
{
surface.flags |= SURFACE_FLAG_BACKFACE;
}
if (!surface.load(prim, q.CommittedTriangleBarycentrics()))
return;
+11 -1
View File
@@ -7,6 +7,7 @@
#include "raytracingHF.hlsli"
#include "stochasticSSRHF.hlsli"
#include "lightingHF.hlsli"
#include "ShaderInterop_DDGI.h"
PUSHCONSTANT(postprocess, PostProcess);
@@ -143,7 +144,10 @@ void main(uint2 DTid : SV_DispatchThreadID)
prim.subsetIndex = q.CommittedGeometryIndex();
Surface surface;
surface.is_frontface = q.CommittedTriangleFrontFace();
if (!q.CommittedTriangleFrontFace())
{
surface.flags |= SURFACE_FLAG_BACKFACE;
}
if (!surface.load(prim, q.CommittedTriangleBarycentrics()))
return;
@@ -198,6 +202,12 @@ void main(uint2 DTid : SV_DispatchThreadID)
lighting.indirect.specular += max(0, EnvironmentReflection_Global(surface));
[branch]
if (GetScene().ddgi.color_texture >= 0)
{
lighting.indirect.diffuse = ddgi_sample_irradiance(surface.P, surface.N);
}
LightingPart combined_lighting = CombineLighting(surface, lighting);
payload.data.xyz += surface.albedo * combined_lighting.diffuse + combined_lighting.specular + surface.emissiveColor;
}
+4 -1
View File
@@ -124,7 +124,10 @@ void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleInterse
prim.subsetIndex = GeometryIndex();
Surface surface;
surface.is_frontface = (HitKind() == HIT_KIND_TRIANGLE_FRONT_FACE);
if (HitKind() != HIT_KIND_TRIANGLE_FRONT_FACE)
{
surface.flags |= SURFACE_FLAG_BACKFACE;
}
if (!surface.load(prim, attr.barycentrics))
return;
@@ -108,6 +108,10 @@ void main(uint3 DTid : SV_DispatchThreadID)
prim.instanceIndex = q.CommittedInstanceID();
prim.subsetIndex = q.CommittedGeometryIndex();
if (!q.CommittedTriangleFrontFace())
{
surface.flags |= SURFACE_FLAG_BACKFACE;
}
if(!surface.load(prim, q.CommittedTriangleBarycentrics()))
break;
+5
View File
@@ -122,6 +122,7 @@ namespace wi::enums
VSTYPE_RAYTRACE_SCREEN,
VSTYPE_POSTPROCESS,
VSTYPE_LENSFLARE,
VSTYPE_DDGI_DEBUG,
// pixel shaders
@@ -188,6 +189,7 @@ namespace wi::enums
PSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL,
PSTYPE_POSTPROCESS_OUTLINE,
PSTYPE_LENSFLARE,
PSTYPE_DDGI_DEBUG,
// geometry shaders
@@ -344,6 +346,9 @@ namespace wi::enums
CSTYPE_SURFEL_BINNING,
CSTYPE_VISIBILITY_RESOLVE,
CSTYPE_VISIBILITY_RESOLVE_MSAA,
CSTYPE_DDGI_RAYTRACE,
CSTYPE_DDGI_UPDATE,
CSTYPE_DDGI_UPDATE_DEPTH,
// raytracing pipelines:
+10
View File
@@ -40,4 +40,14 @@ namespace wi::random
{
return GetRandom(0ull, maxValue);
}
float GetRandom(float minValue, float maxValue)
{
std::uniform_real_distribution<float> distr(minValue, maxValue);
return distr(generator());
}
float GetRandom(float maxValue)
{
return GetRandom(0.0f, maxValue);
}
}
+3
View File
@@ -11,5 +11,8 @@ namespace wi::random
uint64_t GetRandom(uint64_t minValue, uint64_t maxValue);
uint64_t GetRandom(uint64_t maxValue);
float GetRandom(float minValue, float maxValue);
float GetRandom(float maxValue);
};
+10
View File
@@ -523,6 +523,7 @@ void RenderPath3D::Update(float dt)
if (getSceneUpdateEnabled())
{
if (wi::renderer::GetSurfelGIEnabled() ||
wi::renderer::GetDDGIEnabled() ||
wi::renderer::GetRaytracedShadowsEnabled() ||
getAO() == AO_RTAO ||
getRaytracedReflectionEnabled())
@@ -697,6 +698,15 @@ void RenderPath3D::Render() const
);
}
if (wi::renderer::GetDDGIEnabled())
{
wi::renderer::DDGI(
*scene,
cmd,
instanceInclusionMask_DDGI
);
}
});
static const uint32_t drawscene_flags =
+1
View File
@@ -161,6 +161,7 @@ namespace wi
uint8_t instanceInclusionMask_RTReflection = 0xFF;
uint8_t instanceInclusionMask_SurfelGI = 0xFF;
uint8_t instanceInclusionMask_Lightmap = 0xFF;
uint8_t instanceInclusionMask_DDGI = 0xFF;
const wi::graphics::Texture* GetDepthStencil() const override { return &depthBuffer_Main; }
const wi::graphics::Texture* GetGUIBlurredBackground() const override { return &rtGUIBlurredBackground[2]; }
+185 -10
View File
@@ -24,6 +24,7 @@
#include "shaders/ShaderInterop_Postprocess.h"
#include "shaders/ShaderInterop_Raytracing.h"
#include "shaders/ShaderInterop_BVH.h"
#include "shaders/ShaderInterop_DDGI.h"
#include <algorithm>
#include <array>
@@ -96,8 +97,11 @@ bool disableAlbedoMaps = false;
bool forceDiffuseLighting = false;
bool SCREENSPACESHADOWS = false;
bool SURFELGI = false;
float SURFELGI_BOOST = 1.0f;
SURFEL_DEBUG SURFELGI_DEBUG = SURFEL_DEBUG_NONE;
bool DDGI_ENABLED = false;
bool DDGI_DEBUG_ENABLED = false;
uint32_t DDGI_RAYCOUNT = 128u;
float GI_BOOST = 1.0f;
struct VoxelizedSceneData
@@ -581,6 +585,7 @@ PipelineState PSO_sky[SKYRENDERING_COUNT];
enum DEBUGRENDERING
{
DEBUGRENDERING_ENVPROBE,
DEBUGRENDERING_DDGI,
DEBUGRENDERING_GRID,
DEBUGRENDERING_CUBE,
DEBUGRENDERING_LINES,
@@ -748,6 +753,7 @@ void LoadShaders()
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::VS, shaders[VSTYPE_RAYTRACE_SCREEN], "raytrace_screenVS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::VS, shaders[VSTYPE_POSTPROCESS], "postprocessVS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::VS, shaders[VSTYPE_LENSFLARE], "lensFlareVS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::VS, shaders[VSTYPE_DDGI_DEBUG], "ddgi_debugVS.cso"); });
if (device->CheckCapability(GraphicsDeviceCapability::RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS))
{
@@ -840,6 +846,7 @@ void LoadShaders()
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_POSTPROCESS_UPSAMPLE_BILATERAL], "upsample_bilateralPS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_POSTPROCESS_OUTLINE], "outlinePS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_LENSFLARE], "lensFlarePS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::PS, shaders[PSTYPE_DDGI_DEBUG], "ddgi_debugPS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::GS, shaders[GSTYPE_VOXELIZER], "objectGS_voxelizer.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::GS, shaders[GSTYPE_VOXEL], "voxelGS.cso"); });
@@ -998,6 +1005,17 @@ void LoadShaders()
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VISIBILITY_RESOLVE], "visibility_resolveCS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_VISIBILITY_RESOLVE_MSAA], "visibility_resolveCS_MSAA.cso"); });
if (device->CheckCapability(GraphicsDeviceCapability::RAYTRACING))
{
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_DDGI_RAYTRACE], "ddgi_raytraceCS_rtapi.cso", ShaderModel::SM_6_5); });
}
else
{
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_DDGI_RAYTRACE], "ddgi_raytraceCS.cso"); });
}
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_DDGI_UPDATE], "ddgi_updateCS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::CS, shaders[CSTYPE_DDGI_UPDATE_DEPTH], "ddgi_updateCS_depth.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::HS, shaders[HSTYPE_OBJECT], "objectHS.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::HS, shaders[HSTYPE_OBJECT_PREPASS], "objectHS_prepass.cso"); });
wi::jobsystem::Execute(ctx, [](wi::jobsystem::JobArgs args) { LoadShader(ShaderStage::HS, shaders[HSTYPE_OBJECT_PREPASS_ALPHATEST], "objectHS_prepass_alphatest.cso"); });
@@ -1481,6 +1499,14 @@ void LoadShaders()
desc.bs = &blendStates[BSTYPE_OPAQUE];
desc.pt = PrimitiveTopology::TRIANGLELIST;
break;
case DEBUGRENDERING_DDGI:
desc.vs = &shaders[VSTYPE_DDGI_DEBUG];
desc.ps = &shaders[PSTYPE_DDGI_DEBUG];
desc.dss = &depthStencils[DSSTYPE_DEFAULT];
desc.rs = &rasterizers[RSTYPE_FRONT];
desc.bs = &blendStates[BSTYPE_OPAQUE];
desc.pt = PrimitiveTopology::TRIANGLELIST;
break;
case DEBUGRENDERING_GRID:
desc.vs = &shaders[VSTYPE_VERTEXCOLOR];
desc.ps = &shaders[PSTYPE_VERTEXCOLOR];
@@ -2992,7 +3018,7 @@ void UpdatePerFrameData(
frameCB.envprobe_mipcount_rcp = 1.0f / (float)frameCB.envprobe_mipcount;
}
frameCB.surfelgi_boost = GetSurfelGIBoost();
frameCB.gi_boost = GetGIBoost();
frameCB.temporalaa_samplerotation = 0;
if (GetTemporalAAEnabled())
@@ -5654,6 +5680,17 @@ void DrawDebugWorld(
}
if (GetDDGIDebugEnabled())
{
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->EventEnd(cmd);
}
if (gridHelper)
{
device->EventBegin("GridHelper", cmd);
@@ -7951,6 +7988,120 @@ void SurfelGI(
device->EventEnd(cmd);
}
void DDGI(
const wi::scene::Scene& scene,
wi::graphics::CommandList cmd,
uint8_t instanceInclusionMask
)
{
if (!scene.TLAS.IsValid() && !scene.BVH.IsValid())
return;
auto prof_range = wi::profiler::BeginRangeGPU("DDGI", cmd);
device->EventBegin("DDGI", cmd);
BindCommonResources(cmd);
DDGIPushConstants push;
push.instanceInclusionMask = instanceInclusionMask;
push.frameIndex = scene.ddgi_frameIndex;
push.rayCount = std::min(GetDDGIRayCount(), DDGI_MAX_RAYCOUNT);
// Raytracing:
{
device->EventBegin("Raytrace", cmd);
device->BindComputeShader(&shaders[CSTYPE_DDGI_RAYTRACE], cmd);
device->PushConstants(&push, sizeof(push), cmd);
MiscCB cb = {};
float angle = wi::random::GetRandom(0.0f, 1.0f) * XM_2PI;
XMVECTOR axis = XMVectorSet(
wi::random::GetRandom(-1.0f, 1.0f),
wi::random::GetRandom(-1.0f, 1.0f),
wi::random::GetRandom(-1.0f, 1.0f),
0
);
axis = XMVector3Normalize(axis);
XMStoreFloat4x4(&cb.g_xTransform, XMMatrixRotationAxis(axis, angle));
device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(MiscCB), cmd);
const GPUResource* uavs[] = {
&scene.ddgiRayBuffer
};
device->BindUAVs(uavs, 0, arraysize(uavs), cmd);
device->Dispatch(DDGI_PROBE_COUNT, 1, 1, cmd);
device->EventEnd(cmd);
}
{
GPUBarrier barriers[] = {
GPUBarrier::Memory(),
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),
};
device->Barrier(barriers, arraysize(barriers), cmd);
}
// Update:
{
device->EventBegin("Update", cmd);
device->BindComputeShader(&shaders[CSTYPE_DDGI_UPDATE], cmd);
device->PushConstants(&push, sizeof(push), cmd);
const GPUResource* res[] = {
&scene.ddgiRayBuffer,
};
device->BindResources(res, 0, arraysize(res), cmd);
const GPUResource* uavs[] = {
&scene.ddgiColorTexture[1],
};
device->BindUAVs(uavs, 0, arraysize(uavs), cmd);
device->Dispatch(DDGI_PROBE_COUNT, 1, 1, cmd);
device->EventEnd(cmd);
}
// Update Depth:
{
device->EventBegin("Update Depth", cmd);
device->BindComputeShader(&shaders[CSTYPE_DDGI_UPDATE_DEPTH], cmd);
device->PushConstants(&push, sizeof(push), cmd);
const GPUResource* res[] = {
&scene.ddgiRayBuffer,
};
device->BindResources(res, 0, arraysize(res), cmd);
const GPUResource* uavs[] = {
&scene.ddgiDepthTexture[1],
};
device->BindUAVs(uavs, 0, arraysize(uavs), cmd);
device->Dispatch(DDGI_PROBE_COUNT, 1, 1, cmd);
device->EventEnd(cmd);
}
{
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),
};
device->Barrier(barriers, arraysize(barriers), cmd);
}
wi::profiler::EndRange(prof_range);
device->EventEnd(cmd);
}
void Postprocess_Blur_Gaussian(
const Texture& input,
const Texture& temp,
@@ -11829,14 +11980,6 @@ bool GetSurfelGIEnabled()
{
return SURFELGI;
}
void SetSurfelGIBoost(float value)
{
SURFELGI_BOOST = value;
}
float GetSurfelGIBoost()
{
return SURFELGI_BOOST;
}
void SetSurfelGIDebugEnabled(SURFEL_DEBUG value)
{
SURFELGI_DEBUG = value;
@@ -11845,5 +11988,37 @@ SURFEL_DEBUG GetSurfelGIDebugEnabled()
{
return SURFELGI_DEBUG;
}
void SetDDGIEnabled(bool value)
{
DDGI_ENABLED = value;
}
bool GetDDGIEnabled()
{
return DDGI_ENABLED;
}
void SetDDGIDebugEnabled(bool value)
{
DDGI_DEBUG_ENABLED = value;
}
bool GetDDGIDebugEnabled()
{
return DDGI_DEBUG_ENABLED;
}
void SetDDGIRayCount(uint32_t value)
{
DDGI_RAYCOUNT = value;
}
uint32_t GetDDGIRayCount()
{
return DDGI_RAYCOUNT;
}
void SetGIBoost(float value)
{
GI_BOOST = value;
}
float GetGIBoost()
{
return GI_BOOST;
}
}
+14 -2
View File
@@ -342,6 +342,12 @@ namespace wi::renderer
uint8_t instanceInclusionMask = 0xFF
);
void DDGI(
const wi::scene::Scene& scene,
wi::graphics::CommandList cmd,
uint8_t instanceInclusionMask = 0xFF
);
void Postprocess_Blur_Gaussian(
const wi::graphics::Texture& input,
const wi::graphics::Texture& temp,
@@ -770,10 +776,16 @@ namespace wi::renderer
bool GetScreenSpaceShadowsEnabled();
void SetSurfelGIEnabled(bool value);
bool GetSurfelGIEnabled();
void SetSurfelGIBoost(float value);
float GetSurfelGIBoost();
void SetSurfelGIDebugEnabled(SURFEL_DEBUG value);
SURFEL_DEBUG GetSurfelGIDebugEnabled();
void SetDDGIEnabled(bool value);
bool GetDDGIEnabled();
void SetDDGIDebugEnabled(bool value);
bool GetDDGIDebugEnabled();
void SetDDGIRayCount(uint32_t value);
uint32_t GetDDGIRayCount();
void SetGIBoost(float value);
float GetGIBoost();
// Gets pick ray according to the current screen resolution and pointer coordinates. Can be used as input into RayIntersectWorld()
wi::primitive::Ray GetPickRay(long cursorX, long cursorY, const wi::Canvas& canvas, const wi::scene::CameraComponent& camera = wi::scene::GetCamera());
+66
View File
@@ -13,6 +13,7 @@
#include "wiUnorderedMap.h"
#include "shaders/ShaderInterop_SurfelGI.h"
#include "shaders/ShaderInterop_DDGI.h"
using namespace wi::ecs;
using namespace wi::enums;
@@ -1761,6 +1762,51 @@ namespace wi::scene
std::swap(surfelMomentsTexture[0], surfelMomentsTexture[1]);
}
if (wi::renderer::GetDDGIEnabled())
{
ddgi_frameIndex++;
if (!ddgiColorTexture[0].IsValid())
{
ddgi_frameIndex = 0;
GPUBufferDesc buf;
buf.stride = sizeof(DDGIRayDataPacked);
buf.size = buf.stride * DDGI_PROBE_COUNT * DDGI_MAX_RAYCOUNT;
buf.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE;
buf.misc_flags = ResourceMiscFlag::BUFFER_STRUCTURED;
device->CreateBuffer(&buf, nullptr, &ddgiRayBuffer);
device->SetName(&ddgiRayBuffer, "ddgiRayBuffer");
TextureDesc tex;
tex.width = DDGI_COLOR_TEXTURE_WIDTH;
tex.height = DDGI_COLOR_TEXTURE_HEIGHT;
//tex.format = Format::R11G11B10_FLOAT; // not enough precision with this format, causes green hue in GI
tex.format = Format::R16G16B16A16_FLOAT;
tex.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE;
device->CreateTexture(&tex, nullptr, &ddgiColorTexture[0]);
device->SetName(&ddgiColorTexture[0], "ddgiColorTexture[0]");
device->CreateTexture(&tex, nullptr, &ddgiColorTexture[1]);
device->SetName(&ddgiColorTexture[1], "ddgiColorTexture[1]");
tex.width = DDGI_DEPTH_TEXTURE_WIDTH;
tex.height = DDGI_DEPTH_TEXTURE_HEIGHT;
tex.format = Format::R16G16_FLOAT;
tex.bind_flags = BindFlag::UNORDERED_ACCESS | BindFlag::SHADER_RESOURCE;
device->CreateTexture(&tex, nullptr, &ddgiDepthTexture[0]);
device->SetName(&ddgiDepthTexture[0], "ddgiDepthTexture[0]");
device->CreateTexture(&tex, nullptr, &ddgiDepthTexture[1]);
device->SetName(&ddgiDepthTexture[1], "ddgiDepthTexture[1]");
}
std::swap(ddgiColorTexture[0], ddgiColorTexture[1]);
std::swap(ddgiDepthTexture[0], ddgiDepthTexture[1]);
}
else if (ddgiColorTexture[0].IsValid())
{
ddgiColorTexture[0] = {};
ddgiColorTexture[1] = {};
ddgiDepthTexture[0] = {};
ddgiDepthTexture[1] = {};
}
// Shader scene resources:
shaderscene.instancebuffer = device->GetDescriptorIndex(&instanceBuffer, SubresourceType::SRV);
@@ -1810,6 +1856,26 @@ namespace wi::scene
shaderscene.weather.wind.direction = weather.windDirection;
shaderscene.weather.atmosphere = weather.atmosphereParameters;
shaderscene.weather.volumetric_clouds = weather.volumetricCloudParameters;
shaderscene.ddgi.color_texture = device->GetDescriptorIndex(&ddgiColorTexture[0], SubresourceType::SRV);
shaderscene.ddgi.depth_texture = device->GetDescriptorIndex(&ddgiDepthTexture[0], 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;
float3 grid_max = shaderscene.aabb_max;
grid_max.x += 1;
grid_max.y += 1;
grid_max.z += 1;
shaderscene.ddgi.grid_extents.x = abs(grid_max.x - shaderscene.ddgi.grid_min.x);
shaderscene.ddgi.grid_extents.y = abs(grid_max.y - shaderscene.ddgi.grid_min.y);
shaderscene.ddgi.grid_extents.z = abs(grid_max.z - shaderscene.ddgi.grid_min.z);
shaderscene.ddgi.grid_extents_rcp.x = 1.0f / shaderscene.ddgi.grid_extents.x;
shaderscene.ddgi.grid_extents_rcp.y = 1.0f / shaderscene.ddgi.grid_extents.y;
shaderscene.ddgi.grid_extents_rcp.z = 1.0f / shaderscene.ddgi.grid_extents.z;
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.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()
{
+5
View File
@@ -1333,6 +1333,11 @@ namespace wi::scene
wi::graphics::GPUBuffer surfelCellBuffer;
wi::graphics::Texture surfelMomentsTexture[2];
// DDGI resources:
uint ddgi_frameIndex = 0;
wi::graphics::GPUBuffer ddgiRayBuffer;
wi::graphics::Texture ddgiColorTexture[2];
wi::graphics::Texture ddgiDepthTexture[2];
// Environment probe cubemap array state:
static constexpr uint32_t envmapCount = 16;
+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 = 18;
const int revision = 19;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);
+1
View File
@@ -83,6 +83,7 @@ Screen Space Contact Shadows
Stochastic alphatest transparency
Surfel GI
HDR display output
Dynamic Diffuse Global Illumination (DDGI)
GLTF 2.0 extensions supported:
KHR_materials_unlit