diff --git a/CHANGELOG.md b/CHANGELOG.md index 026d02a..ebadc4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Improved cone tracing direction selection. - Removed cone tracing bias. - Removed redundant matrix multiplication in voxelization step. +- Improved voxel visibility function. ### Fixed diff --git a/ShaderLibrary/Radiances/Pixel.cginc b/ShaderLibrary/Radiances/Pixel.cginc index 2eee857..1699cf6 100644 --- a/ShaderLibrary/Radiances/Pixel.cginc +++ b/ShaderLibrary/Radiances/Pixel.cginc @@ -35,7 +35,7 @@ if (notInRange || (spotFalloff <= 0.0) || (data.NdotL <= 0.0)) continue; radiance += - VoxelVisibility(data.voxelPosition + data.vecN, lightSource.voxelPosition) + VXGI_VoxelVisibility((data.voxelPosition + data.vecN) / Resolution, lightSource.voxelPosition / Resolution) * GeneralBRDF(data) * data.NdotL * spotFalloff diff --git a/ShaderLibrary/Radiances/Sampler.cginc b/ShaderLibrary/Radiances/Sampler.cginc index be6f142..0d29e86 100644 --- a/ShaderLibrary/Radiances/Sampler.cginc +++ b/ShaderLibrary/Radiances/Sampler.cginc @@ -1,100 +1,74 @@ -#ifndef VXGI_RADIANCES_SAMPLER - #define VXGI_RADIANCES_SAMPLER +#ifndef VXGI_SHADERLIBRARY_RADIANCES_SAMPLER +#define VXGI_SHADERLIBRARY_RADIANCES_SAMPLER - #ifdef RADIANCE_POINT_SAMPLER - #define RADIANCE_SAMPLER point_clamp_sampler - #else - #define RADIANCE_SAMPLER linear_clamp_sampler - #endif - - #define LERP_OCCLUSION(level, position, fraction) lerp(SAMPLE_OCCLUSION(level - 1, position), SAMPLE_OCCLUSION(level, position), fraction) - #define LERP_RADIANCE(level, position, fraction) lerp(SAMPLE_RADIANCE(level - 1, position), SAMPLE_RADIANCE(level, position), fraction) - #define SAMPLE_OCCLUSION(level, position) SAMPLE_RADIANCE(level, position).a - #define SAMPLE_RADIANCE(level, position) Radiances[level].SampleLevel(RADIANCE_SAMPLER, position, 0.0) +#ifdef RADIANCE_POINT_SAMPLER + #define RADIANCE_SAMPLER point_clamp_sampler +#else + #define RADIANCE_SAMPLER linear_clamp_sampler +#endif - #include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Variables.cginc" +#define LERP_RADIANCE(level, position, fraction) lerp(SAMPLE_RADIANCE(level - 1, position), SAMPLE_RADIANCE(level, position), fraction) +#define SAMPLE_RADIANCE(level, position) Radiances[level].SampleLevel(RADIANCE_SAMPLER, position, 0.0) - Texture3D Radiance0; - Texture3D Radiance1; - Texture3D Radiance2; - Texture3D Radiance3; - Texture3D Radiance4; - Texture3D Radiance5; - Texture3D Radiance6; - Texture3D Radiance7; - Texture3D Radiance8; - static Texture3D Radiances[9] = { - Radiance0, - Radiance1, - Radiance2, - Radiance3, - Radiance4, - Radiance5, - Radiance6, - Radiance7, - Radiance8, - }; +#include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Variables.cginc" - float SampleLevel(float size) - { - return size <= 1.0 ? size : log2(size) + 1; - } +Texture3D Radiance0; +Texture3D Radiance1; +Texture3D Radiance2; +Texture3D Radiance3; +Texture3D Radiance4; +Texture3D Radiance5; +Texture3D Radiance6; +Texture3D Radiance7; +Texture3D Radiance8; +static Texture3D Radiances[9] = { + Radiance0, + Radiance1, + Radiance2, + Radiance3, + Radiance4, + Radiance5, + Radiance6, + Radiance7, + Radiance8, +}; - float SampleOcclusion(float3 position, float size) - { - float level = clamp(SampleLevel(size), 0.0, 8.999999); - uint levelFloor = level; +float SampleLevel(float size) +{ + return size <= 1.0 ? size : log2(size) + 1; +} - if (level <= 1.0) { - return lerp(0.0, SAMPLE_OCCLUSION(0, position), level); - } else { - switch (levelFloor) { - case 1: - return LERP_OCCLUSION(1, position, frac(level)); - case 2: - return LERP_OCCLUSION(2, position, frac(level)); - case 3: - return LERP_OCCLUSION(3, position, frac(level)); - case 4: - return LERP_OCCLUSION(4, position, frac(level)); - case 5: - return LERP_OCCLUSION(5, position, frac(level)); - case 6: - return LERP_OCCLUSION(6, position, frac(level)); - case 7: - return LERP_OCCLUSION(7, position, frac(level)); - default: - return LERP_OCCLUSION(8, position, frac(level)); - } - } - } +float VXGI_VoxelOpacity(float3 position) +{ + return Radiance0.SampleLevel(RADIANCE_SAMPLER, position, 0.0).a; +} - float4 SampleRadiance(float3 position, float size) - { - float level = clamp(SampleLevel(size), 0.0, 8.999999); - uint levelFloor = level; +float4 SampleRadiance(float3 position, float size) +{ + float level = clamp(SampleLevel(size), 0.0, 8.999999); + uint levelFloor = level; - if (level <= 1.0) { - return lerp(0.0, SAMPLE_RADIANCE(0, position), level); - } else { - switch (levelFloor) { - case 1: - return LERP_RADIANCE(1, position, frac(level)); - case 2: - return LERP_RADIANCE(2, position, frac(level)); - case 3: - return LERP_RADIANCE(3, position, frac(level)); - case 4: - return LERP_RADIANCE(4, position, frac(level)); - case 5: - return LERP_RADIANCE(5, position, frac(level)); - case 6: - return LERP_RADIANCE(6, position, frac(level)); - case 7: - return LERP_RADIANCE(7, position, frac(level)); - default: - return LERP_RADIANCE(8, position, frac(level)); - } + if (level <= 1.0) { + return lerp(0.0, SAMPLE_RADIANCE(0, position), level); + } else { + switch (levelFloor) { + case 1: + return LERP_RADIANCE(1, position, frac(level)); + case 2: + return LERP_RADIANCE(2, position, frac(level)); + case 3: + return LERP_RADIANCE(3, position, frac(level)); + case 4: + return LERP_RADIANCE(4, position, frac(level)); + case 5: + return LERP_RADIANCE(5, position, frac(level)); + case 6: + return LERP_RADIANCE(6, position, frac(level)); + case 7: + return LERP_RADIANCE(7, position, frac(level)); + default: + return LERP_RADIANCE(8, position, frac(level)); } } -#endif +} +#endif // VXGI_SHADERLIBRARY_RADIANCES_SAMPLER diff --git a/ShaderLibrary/Radiances/Voxel.cginc b/ShaderLibrary/Radiances/Voxel.cginc index 7a0fc0e..ce56599 100644 --- a/ShaderLibrary/Radiances/Voxel.cginc +++ b/ShaderLibrary/Radiances/Voxel.cginc @@ -34,7 +34,7 @@ if (notInRange || (spotFalloff <= 0.0) || (data.NdotL <= 0.0)) continue; radiance += - VoxelVisibility(data.voxelPosition + data.vecL / data.NdotL, lightSource.voxelPosition) + VXGI_VoxelVisibility((data.voxelPosition + data.vecL / data.NdotL) / Resolution, lightSource.voxelPosition / Resolution) * data.NdotL * spotFalloff * lightSource.Attenuation(localPosition); diff --git a/ShaderLibrary/Variables.cginc b/ShaderLibrary/Variables.cginc index 91f446a..50ad2f3 100644 --- a/ShaderLibrary/Variables.cginc +++ b/ShaderLibrary/Variables.cginc @@ -1,51 +1,63 @@ -#ifndef VXGI_VARIABLES - #define VXGI_VARIABLES +#ifndef VXGI_SHADERLIBRARY_VARIABLES +#define VXGI_SHADERLIBRARY_VARIABLES - #include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Structs/LightSource.hlsl" +#include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Structs/LightSource.hlsl" - uint Resolution; - uint LightCount; - float4x4 VoxelToWorld; - float4x4 WorldToVoxel; - SamplerState point_clamp_sampler; - SamplerState linear_clamp_sampler; - StructuredBuffer LightSources; +uint Resolution; +uint LightCount; +float4x4 VoxelToWorld; +float4x4 WorldToVoxel; +SamplerState point_clamp_sampler; +SamplerState linear_clamp_sampler; +StructuredBuffer LightSources; - static float ConeDirectionThreshold = sin(atan(1.0/3.0)); +static float ConeDirectionThreshold = sin(atan(1.0/3.0)); - // Cone tracing direction for indirect diffuse calculations - static float3 Directions[32] = { - float3(+0.000000, +1.000000, +0.000000), - float3(+0.000000, -1.000000, +0.000000), - float3(+0.000000, +0.187595, -0.982245), - float3(+0.000000, -0.187595, +0.982245), - float3(+0.000000, +0.745356, -0.666656), - float3(+0.000000, -0.745356, +0.666656), - float3(+0.000000, +0.794654, +0.607060), - float3(+0.000000, -0.794654, -0.607060), - float3(+0.356818, +0.333334, +0.872681), - float3(+0.356818, -0.333334, -0.872681), - float3(-0.356818, +0.333334, +0.872681), - float3(-0.356818, -0.333334, -0.872681), - float3(+0.525736, +0.794654, -0.303524), - float3(+0.525736, -0.794654, +0.303524), - float3(-0.525736, +0.794654, -0.303524), - float3(-0.525736, -0.794654, +0.303524), - float3(+0.577350, +0.333334, -0.745356), - float3(+0.577350, -0.333334, +0.745356), - float3(-0.577350, +0.333334, -0.745356), - float3(-0.577350, -0.333334, +0.745356), - float3(+0.577350, +0.745356, +0.333334), - float3(+0.577350, -0.745356, -0.333334), - float3(-0.577350, +0.745356, +0.333334), - float3(-0.577350, -0.745356, -0.333334), - float3(+0.850648, +0.187595, +0.491129), - float3(+0.850648, -0.187595, -0.491129), - float3(-0.850648, +0.187595, +0.491129), - float3(-0.850648, -0.187595, -0.491129), - float3(+0.934174, +0.333334, -0.127319), - float3(+0.934174, -0.333334, +0.127319), - float3(-0.934174, +0.333334, -0.127319), - float3(-0.934174, -0.333334, +0.127319), - }; -#endif +// Cone tracing direction for indirect diffuse calculations +static float3 Directions[32] = { + float3(+0.000000, +1.000000, +0.000000), + float3(+0.000000, -1.000000, +0.000000), + float3(+0.000000, +0.187595, -0.982245), + float3(+0.000000, -0.187595, +0.982245), + float3(+0.000000, +0.745356, -0.666656), + float3(+0.000000, -0.745356, +0.666656), + float3(+0.000000, +0.794654, +0.607060), + float3(+0.000000, -0.794654, -0.607060), + float3(+0.356818, +0.333334, +0.872681), + float3(+0.356818, -0.333334, -0.872681), + float3(-0.356818, +0.333334, +0.872681), + float3(-0.356818, -0.333334, -0.872681), + float3(+0.525736, +0.794654, -0.303524), + float3(+0.525736, -0.794654, +0.303524), + float3(-0.525736, +0.794654, -0.303524), + float3(-0.525736, -0.794654, +0.303524), + float3(+0.577350, +0.333334, -0.745356), + float3(+0.577350, -0.333334, +0.745356), + float3(-0.577350, +0.333334, -0.745356), + float3(-0.577350, -0.333334, +0.745356), + float3(+0.577350, +0.745356, +0.333334), + float3(+0.577350, -0.745356, -0.333334), + float3(-0.577350, +0.745356, +0.333334), + float3(-0.577350, -0.745356, -0.333334), + float3(+0.850648, +0.187595, +0.491129), + float3(+0.850648, -0.187595, -0.491129), + float3(-0.850648, +0.187595, +0.491129), + float3(-0.850648, -0.187595, -0.491129), + float3(+0.934174, +0.333334, -0.127319), + float3(+0.934174, -0.333334, +0.127319), + float3(-0.934174, +0.333334, -0.127319), + float3(-0.934174, -0.333334, +0.127319), +}; + +static float3 VXGI_VoxelSizes[] = { + 1.0 / Resolution, + 2.0 / Resolution, + 4.0 / Resolution, + 8.0 / Resolution, + 16.0 / Resolution, + 32.0 / Resolution, + 64.0 / Resolution, + 128.0 / Resolution, + 256.0 / Resolution +}; +#endif // VXGI_SHADERLIBRARY_VARIABLES diff --git a/ShaderLibrary/Visibility.cginc b/ShaderLibrary/Visibility.cginc index 1de098e..3586f7b 100644 --- a/ShaderLibrary/Visibility.cginc +++ b/ShaderLibrary/Visibility.cginc @@ -1,25 +1,28 @@ -#ifndef VXGI_VISIBILITY - #define VXGI_VISIBILITY +#ifndef VXGI_SHADERLIBRARY_VISIBILITY +#define VXGI_SHADERLIBRARY_VISIBILITY - #include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Variables.cginc" - #include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Utilities.cginc" - #include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Radiances/Sampler.cginc" +#include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Variables.cginc" +#include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Utilities.cginc" +#include "Packages/com.looooong.srp.vxgi/ShaderLibrary/Radiances/Sampler.cginc" - // Calculate visibility between 2 points in voxel space - float VoxelVisibility(float3 p1, float3 p2) - { - float occlusion = 0.0; - float3 direction = normalize(p2 - p1); - float3 step = direction / Resolution; +// Calculate visibility between 2 points in voxel space +float VXGI_VoxelVisibility(float3 p1, float3 p2) +{ + uint level = 0; + float opacity = 0.0; + float stepDistance = distance(p1, p2); + float stepSize = 0.5 * VXGI_VoxelSizes[level]; + float3 stepDirection = normalize(p2 - p1); + float3 step = stepSize * stepDirection; - for ( - float3 coordinate = p1 / Resolution + step; - occlusion < 1.0 && TextureSDF(coordinate) > 0.0 && dot(mad(-coordinate, Resolution, p2), direction) > 0.5; - coordinate += 0.5 * step - ) { - occlusion += (1.0 - occlusion) * SampleOcclusion(coordinate, 1.0); - } - - return 1.0 - occlusion; + for ( + p1 += step, stepDistance -= stepSize; + opacity < 1.0 && stepDistance > 0.0; + p1 += step, stepDistance -= stepSize + ) { + if (TextureSDF(p1) > 0.0) opacity += (1.0 - opacity) * VXGI_VoxelOpacity(p1); } -#endif + + return 1.0 - opacity; +} +#endif // VXGI_SHADERLIBRARY_VISIBILITY