voxel GI quality update; added cornell-box model for better testing

This commit is contained in:
turanszkij
2018-02-27 17:22:58 +00:00
parent dd11aa891e
commit 76c96199e1
7 changed files with 60 additions and 45 deletions
+2 -2
View File
@@ -59,14 +59,14 @@ CBUFFER(WorldCB, CBSLOT_RENDERER_WORLD)
float3 g_xWorld_Fog; // Fog Start,End,Height
float g_xWorld_SpecularAA;
float g_xWorld_VoxelRadianceDataSize;
float g_xWorld_VoxelRadianceDataSize_Inverse;
uint g_xWorld_VoxelRadianceDataRes;
float g_xWorld_VoxelRadianceDataRes_Inverse;
uint g_xWorld_VoxelRadianceDataMIPs;
uint g_xWorld_VoxelRadianceConeTracingQuality;
uint g_xWorld_VoxelRadianceConeTracingQuality_Inverse;
float g_xWorld_VoxelRadianceConeTracingQuality_Inverse;
float g_xWorld_VoxelRadianceFalloff;
bool g_xWorld_VoxelRadianceReflectionsEnabled;
float xPadding1_WorldCB;
float3 g_xWorld_VoxelRadianceDataCenter;
bool g_xWorld_AdvancedRefractions;
uint3 g_xWorld_EntityCullingTileCount;
+13 -4
View File
@@ -704,10 +704,19 @@ inline void VoxelRadiance(in Surface surface, inout float3 diffuse, inout float3
{
[branch]if (g_xWorld_VoxelRadianceDataRes != 0)
{
float3 diff = (surface.P - g_xWorld_VoxelRadianceDataCenter) / g_xWorld_VoxelRadianceDataRes / g_xWorld_VoxelRadianceDataSize;
float3 uvw = diff * float3(0.5f, -0.5f, 0.5f) + 0.5f;
diff = abs(diff);
float blend = pow(saturate(max(diff.x, max(diff.y, diff.z))), 4);
// Convert world space surface pos to voxel grid space:
float3 voxelSpacePos = surface.P - g_xWorld_VoxelRadianceDataCenter;
// offset by half a voxel in the direction of the surface normal (try to avoid self-occlusion)
voxelSpacePos += surface.N * 0.5f;
// normalize voxel space pos to [-1, 1]:
voxelSpacePos *= g_xWorld_VoxelRadianceDataSize_Inverse;
voxelSpacePos *= g_xWorld_VoxelRadianceDataRes_Inverse;
// calculate uvw coords into voxel texture:
float3 uvw = voxelSpacePos * float3(0.5f, -0.5f, 0.5f) + 0.5f;
// determine blending factor (we will blend out voxel GI on grid edges):
voxelSpacePos = saturate(abs(voxelSpacePos));
float blend = pow(max(voxelSpacePos.x, max(voxelSpacePos.y, voxelSpacePos.z)), 4);
float4 radiance = ConeTraceRadiance(texture_voxelradiance, uvw, surface.N);
diffuse += lerp(radiance.rgb, 0, blend);
+41 -36
View File
@@ -3,63 +3,64 @@
#include "globals.hlsli"
static const float3 CONES[] = {
float3(0.355512, -0.709318, -0.102371),
float3(0.534186, 0.71511, -0.115167),
float3(-0.87866, 0.157139, -0.115167),
float3(0.140679, -0.475516, -0.0639818),
float3(-0.0796121, 0.158842, -0.677075),
float3(-0.0759516, -0.101676, -0.483625),
float3(0.12493, -0.0223423, -0.483625),
float3(-0.0720074, 0.243395, -0.967251),
float3(-0.207641, 0.414286, 0.187755),
float3(-0.277332, -0.371262, 0.187755),
float3(0.63864, -0.114214, 0.262857),
float3(-0.184051, 0.622119, 0.262857),
float3(0.110007, -0.219486, 0.435574),
float3(0.235085, 0.314707, 0.696918),
float3(-0.290012, 0.0518654, 0.522688),
float3(0.0975089, -0.329594, 0.609803)
float3(0.57735, 0.57735, 0.57735),
float3(0.57735, -0.57735, -0.57735),
float3(-0.57735, 0.57735, -0.57735),
float3(-0.57735, -0.57735, 0.57735),
float3(-0.903007, -0.182696, -0.388844),
float3(-0.903007, 0.182696, 0.388844),
float3(0.903007, -0.182696, 0.388844),
float3(0.903007, 0.182696, -0.388844),
float3(-0.388844, -0.903007, -0.182696),
float3(0.388844, -0.903007, 0.182696),
float3(0.388844, 0.903007, -0.182696),
float3(-0.388844, 0.903007, 0.182696),
float3(-0.182696, -0.388844, -0.903007),
float3(0.182696, 0.388844, -0.903007),
float3(-0.182696, 0.388844, 0.903007),
float3(0.182696, -0.388844, 0.903007)
};
inline float4 ConeTraceRadiance(in Texture3D<float4> voxels, in float3 uvw, in float3 N)
{
const uint numCones = clamp(g_xWorld_VoxelRadianceConeTracingQuality, 1, 16);
// Cone tracing:
float4 radiance = 0;
for (uint cone = 0; cone < numCones; ++cone)
for (uint cone = 0; cone < g_xWorld_VoxelRadianceConeTracingQuality; ++cone) // quality is between 1 and 16 cones
{
// try to approximate a hemisphere from random points inside a sphere:
float3 coneVec = CONES[cone];
// if point on sphere is facing below normal (so it's located on bottom hemisphere), put it on the opposite hemisphere instead:
coneVec *= dot(coneVec, N) < 0 ? -1 : 1;
// try to avoid cone extending below horizon by offsetting a bit by normal:
coneVec += N * 0.1f;
coneVec *= g_xWorld_VoxelRadianceDataRes_Inverse * float3(1, -1, 1);
float4 accumulation = 0;
float3 color = 0;
float alpha = 0;
float3 tc = uvw;
uint i = 0;
while (accumulation.a < 1 && !any(tc - saturate(tc)))
while (alpha < 1 && !any(tc - saturate(tc)))
{
float mip = 0.7 * i;
float mip = 0.8 * i;
tc += coneVec * (1 + mip);
float4 sam = voxels.SampleLevel(sampler_linear_clamp, tc, mip);
accumulation.a += sam.a;
accumulation.rgb += sam.rgb * sam.a;
float a = 1 - alpha;
color += a * sam.rgb;
alpha += a * sam.a;
if (mip >= (float)g_xWorld_VoxelRadianceDataMIPs)
break;
++i;
}
float searchDist = length(uvw - tc) * g_xWorld_VoxelRadianceDataRes * g_xWorld_VoxelRadianceFalloff;
accumulation.a /= searchDist;
radiance += accumulation;
radiance += float4(color, alpha);
}
radiance /= numCones;
// final radiance is average of all the cones radiances
radiance *= g_xWorld_VoxelRadianceConeTracingQuality_Inverse;
radiance.a = saturate(radiance.a);
return max(0, radiance);
@@ -69,24 +70,28 @@ inline float4 ConeTraceReflection(in Texture3D<float4> voxels, in float3 uvw, in
{
float aperture = pow(roughness, 4);
float3 coneVec = reflect(-V, N) / g_xWorld_VoxelRadianceDataRes * float3(1, -1, 1);
float4 accumulation = 0;
float3 tc = uvw + coneVec;
float NdotV = saturate(dot(N, V));
coneVec *= lerp(0.25, 4, pow(1 - NdotV, 8));
float3 color = 0;
float alpha = 0;
// TODO: this can result in huge loops if ray enters empty space.
// Simply limiting iteration count is not good enough solution because most reflections won't be found that way.
// Need to have at least some form of binary search. Maybe we could reuse lower mip to find where to backtrace?
uint i = 0;
while (accumulation.a < 1 && !any(tc - saturate(tc)))
while (alpha < 1 && !any(tc - saturate(tc)))
{
float mip = aperture * i;
tc += coneVec * (1 + mip);
float4 sam = voxels.SampleLevel(sampler_linear_clamp, tc, mip);
accumulation.a += sam.a;
accumulation.rgb += sam.rgb * sam.a;
float a = 1 - alpha;
color += a * sam.rgb;
alpha += a * sam.a;
if (mip >= (float)g_xWorld_VoxelRadianceDataMIPs)
{
@@ -96,7 +101,7 @@ inline float4 ConeTraceReflection(in Texture3D<float4> voxels, in float3 uvw, in
++i;
}
return float4(max(0, accumulation.rgb), saturate(accumulation.a));
return float4(max(0, color), saturate(alpha));
}
#endif
+2 -1
View File
@@ -6293,10 +6293,11 @@ void wiRenderer::UpdateWorldCB(GRAPHICSTHREAD threadID)
value.mZenith = world.zenith;
value.mSpecularAA = SPECULARAA;
value.mVoxelRadianceDataSize = voxelSceneData.voxelsize;
value.mVoxelRadianceDataSize_Inverse = 1.0f / (float)value.mVoxelRadianceDataSize;
value.mVoxelRadianceDataRes = GetVoxelRadianceEnabled() ? (UINT)voxelSceneData.res : 0;
value.mVoxelRadianceDataRes_Inverse = 1.0f / (float)value.mVoxelRadianceDataRes;
value.mVoxelRadianceDataMIPs = voxelSceneData.mips;
value.mVoxelRadianceDataConeTracingQuality = voxelSceneData.coneTracingQuality;
value.mVoxelRadianceDataConeTracingQuality = max(min(voxelSceneData.coneTracingQuality, 16), 1);
value.mVoxelRadianceDataConeTracingQuality_Inverse = 1.0f / (float)value.mVoxelRadianceDataConeTracingQuality;
value.mVoxelRadianceDataFalloff = voxelSceneData.falloff;
value.mVoxelRadianceReflectionsEnabled = voxelSceneData.reflectionsEnabled;
+1 -1
View File
@@ -133,6 +133,7 @@ public:
XMFLOAT3 mFog;
float mSpecularAA;
float mVoxelRadianceDataSize;
float mVoxelRadianceDataSize_Inverse;
UINT mVoxelRadianceDataRes;
float mVoxelRadianceDataRes_Inverse;
UINT mVoxelRadianceDataMIPs;
@@ -140,7 +141,6 @@ public:
float mVoxelRadianceDataConeTracingQuality_Inverse;
float mVoxelRadianceDataFalloff;
BOOL mVoxelRadianceReflectionsEnabled;
float pad1;
XMFLOAT3 mVoxelRadianceDataCenter;
BOOL mAdvancedRefractions;
XMUINT3 mEntityCullingTileCount;
+1 -1
View File
@@ -9,7 +9,7 @@ namespace wiVersion
// minor features, major updates
const int minor = 16;
// minor bug fixes, alterations, refactors, updates
const int revision = 8;
const int revision = 9;
long GetVersion()
Binary file not shown.